Full Code of g1879/DrissionPage for AI

master 4bebd1354f61 cached
166 files
1.3 MB
336.5k tokens
2576 symbols
1 requests
Download .txt
Showing preview only (1,355K chars total). Download the full file or copy to clipboard to get everything.
Repository: g1879/DrissionPage
Branch: master
Commit: 4bebd1354f61
Files: 166
Total size: 1.3 MB

Directory structure:
gitextract_pk4tkf1v/

├── .github/
│   └── FUNDING.yml
├── .gitignore
├── DrissionPage/
│   ├── __init__.py
│   ├── __init__.pyi
│   ├── _base/
│   │   ├── base.py
│   │   ├── base.pyi
│   │   ├── chromium.py
│   │   ├── chromium.pyi
│   │   ├── driver.py
│   │   └── driver.pyi
│   ├── _configs/
│   │   ├── chromium_options.py
│   │   ├── chromium_options.pyi
│   │   ├── configs.ini
│   │   ├── options_manage.py
│   │   ├── options_manage.pyi
│   │   ├── session_options.py
│   │   └── session_options.pyi
│   ├── _elements/
│   │   ├── chromium_element.py
│   │   ├── chromium_element.pyi
│   │   ├── none_element.py
│   │   ├── none_element.pyi
│   │   ├── session_element.py
│   │   └── session_element.pyi
│   ├── _functions/
│   │   ├── browser.py
│   │   ├── browser.pyi
│   │   ├── by.py
│   │   ├── cli.py
│   │   ├── cookies.py
│   │   ├── cookies.pyi
│   │   ├── elements.py
│   │   ├── elements.pyi
│   │   ├── keys.py
│   │   ├── keys.pyi
│   │   ├── locator.py
│   │   ├── locator.pyi
│   │   ├── settings.py
│   │   ├── settings.pyi
│   │   ├── texts.py
│   │   ├── tools.py
│   │   ├── tools.pyi
│   │   ├── web.py
│   │   └── web.pyi
│   ├── _pages/
│   │   ├── chromium_base.py
│   │   ├── chromium_base.pyi
│   │   ├── chromium_frame.py
│   │   ├── chromium_frame.pyi
│   │   ├── chromium_page.py
│   │   ├── chromium_page.pyi
│   │   ├── chromium_tab.py
│   │   ├── chromium_tab.pyi
│   │   ├── mix_tab.py
│   │   ├── mix_tab.pyi
│   │   ├── session_page.py
│   │   ├── session_page.pyi
│   │   ├── web_page.py
│   │   └── web_page.pyi
│   ├── _units/
│   │   ├── actions.py
│   │   ├── actions.pyi
│   │   ├── clicker.py
│   │   ├── clicker.pyi
│   │   ├── console.py
│   │   ├── console.pyi
│   │   ├── cookies_setter.py
│   │   ├── cookies_setter.pyi
│   │   ├── downloader.py
│   │   ├── downloader.pyi
│   │   ├── listener.py
│   │   ├── listener.pyi
│   │   ├── rect.py
│   │   ├── rect.pyi
│   │   ├── screencast.py
│   │   ├── screencast.pyi
│   │   ├── scroller.py
│   │   ├── scroller.pyi
│   │   ├── selector.py
│   │   ├── selector.pyi
│   │   ├── setter.py
│   │   ├── setter.pyi
│   │   ├── states.py
│   │   ├── states.pyi
│   │   ├── waiter.py
│   │   └── waiter.pyi
│   ├── common.py
│   ├── errors.py
│   ├── items.py
│   └── version.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── docs_en/
│   ├── .nojekyll
│   ├── ChromiumPage/
│   │   ├── actions.md
│   │   ├── browser_options.md
│   │   ├── create_page_object.md
│   │   ├── element_operation.md
│   │   ├── frame_operation.md
│   │   ├── get_element_info.md
│   │   ├── get_elements.md
│   │   ├── get_page_info.md
│   │   ├── introduction.md
│   │   ├── network_listener.md
│   │   ├── page_operation.md
│   │   ├── screen_recording.md
│   │   ├── tab_operation.md
│   │   ├── upload_files.md
│   │   ├── visit_web_page.md
│   │   └── waiting.md
│   ├── MixPage/
│   │   └── introduction.md
│   ├── Q&A.md
│   ├── README_en.md
│   ├── SessionPage/
│   │   ├── create_page_object.md
│   │   ├── get_element_info.md
│   │   ├── get_elements.md
│   │   ├── get_page_info.md
│   │   ├── introduction.md
│   │   ├── session_options.md
│   │   ├── set_session.md
│   │   └── visit_web_page.md
│   ├── WebPage/
│   │   ├── create_page_object.md
│   │   ├── introduction.md
│   │   ├── mode_switch.md
│   │   └── webpage_function.md
│   ├── advance/
│   │   ├── accelerate_reading.md
│   │   ├── commands.md
│   │   ├── errors.md
│   │   ├── ini_file.md
│   │   ├── packaging.md
│   │   ├── settings.md
│   │   └── tools.md
│   ├── cooperation.md
│   ├── demos/
│   │   ├── douban_book_pics.md
│   │   ├── login_gitee.md
│   │   ├── maoyan_TOP100.md
│   │   ├── multithreading_with_tabs.md
│   │   └── starbucks_pics.md
│   ├── download/
│   │   ├── DownloadKit.md
│   │   ├── browser.md
│   │   └── introduction.md
│   ├── features/
│   │   ├── features_demos/
│   │   │   ├── compare_with_requests.md
│   │   │   ├── compare_with_selenium.md
│   │   │   ├── download_file.md
│   │   │   ├── get_element_attributes.md
│   │   │   └── switch_mode.md
│   │   └── intimate_design.md
│   ├── get_elements/
│   │   ├── cheat_sheet.md
│   │   ├── introduction.md
│   │   ├── more.md
│   │   ├── not_found.md
│   │   ├── simplify.md
│   │   └── usage.md
│   ├── get_start/
│   │   ├── basic_concept.md
│   │   ├── before_start.md
│   │   ├── examples/
│   │   │   ├── control_browser.md
│   │   │   ├── data_packets.md
│   │   │   └── switch_mode.md
│   │   ├── import.md
│   │   └── installation.md
│   ├── history/
│   │   ├── 1.x.md
│   │   ├── 2.x.md
│   │   ├── 3.x.md
│   │   ├── 4.x.md
│   │   └── statement.md
│   ├── usage_introduction.md
│   └── whatsnew/
│       ├── 3_2.md
│       └── 4_0.md
├── requirements.txt
└── setup.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/


================================================
FILE: DrissionPage/__init__.py
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.

允许任何人以个人身份使用或分发本项目源代码,但仅限于学习和合法非盈利目的。
个人或组织如未获得版权持有人授权,不得将本项目以源代码或二进制形式用于商业行为。

使用本项目需满足以下条款,如使用过程中出现违反任意一项条款的情形,授权自动失效。
* 禁止将DrissionPage应用到任何可能违反当地法律规定和道德约束的项目中
* 禁止将DrissionPage用于任何可能有损他人利益的项目中
* 禁止将DrissionPage用于攻击与骚扰行为
* 遵守Robots协议,禁止将DrissionPage用于采集法律或系统Robots协议不允许的数据

使用DrissionPage发生的一切行为均由使用人自行负责。
因使用DrissionPage进行任何行为所产生的一切纠纷及后果均与版权持有人无关,
版权持有人不承担任何使用DrissionPage带来的风险和损失。
版权持有人不对DrissionPage可能存在的缺陷导致的任何损失负任何责任。
"""
from ._base.chromium import Chromium
from ._configs.chromium_options import ChromiumOptions
from ._configs.session_options import SessionOptions
from ._pages.chromium_page import ChromiumPage
from ._pages.session_page import SessionPage
from ._pages.web_page import WebPage
from .version import __version__


================================================
FILE: DrissionPage/__init__.pyi
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from ._base.chromium import Chromium
from ._configs.chromium_options import ChromiumOptions
from ._configs.session_options import SessionOptions
from ._pages.chromium_page import ChromiumPage
from ._pages.session_page import SessionPage
from ._pages.web_page import WebPage
from .version import __version__


__all__ = ['WebPage', 'ChromiumPage', 'Chromium', 'ChromiumOptions', 'SessionOptions', 'SessionPage', '__version__']


================================================
FILE: DrissionPage/_base/base.py
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from abc import abstractmethod
from copy import copy
from pathlib import Path
from re import sub
from urllib.parse import quote

from DrissionGet import DrissionGet
from requests import Session

from .._configs.session_options import SessionOptions
from .._elements.none_element import NoneElement
from .._functions.elements import get_frame, get_eles
from .._functions.locator import get_loc
from .._functions.settings import Settings as _S
from .._functions.web import format_html
from ..errors import ElementNotFoundError, LocatorError


class BaseParser(object):
    def __call__(self, locator):
        return self.ele(locator)

    def ele(self, locator, index=1, timeout=None):
        return self._ele(locator, timeout, index=index, method='ele()')

    def eles(self, locator, timeout=None):
        return self._ele(locator, timeout, index=None)

    def find(self, locators, any_one=True, first_ele=True, timeout=None):
        if 'Session' in self._type:
            timeout = 0
        if timeout is None:
            timeout = self.timeout
        r = get_eles(locators, self, any_one, first_ele, timeout)
        if any_one:
            for ele in r:
                if r[ele]:
                    return ele, r[ele]
            return None, None
        return r

    # ----------------以下属性或方法待后代实现----------------
    @property
    def html(self):
        return ''

    def s_ele(self, locator=None):
        pass

    def s_eles(self, locator):
        pass

    def _ele(self, locator, timeout=None, index=1, raise_err=None, method=None):
        pass

    def _find_elements(self, locator, timeout, index=1, relative=False, raise_err=None):
        pass


class BaseElement(BaseParser):
    def __init__(self, owner=None):
        self.owner = owner
        self._type = 'BaseElement'

    def get_frame(self, loc_or_ind, timeout=None):
        if not isinstance(loc_or_ind, (int, str, tuple)):
            raise ValueError(_S._lang.join(_S._lang.INCORRECT_TYPE_, 'loc_or_ind',
                                           ALLOW_TYPE=_S._lang.LOC_OR_IND, CURR_VAL=loc_or_ind))
        return get_frame(self, loc_ind_ele=loc_or_ind, timeout=timeout)

    def _ele(self, locator, timeout=None, index=1, relative=False, raise_err=None, method=None):
        if hasattr(locator, '_type'):
            return locator
        if timeout is None:
            timeout = self.timeout
        r = self._find_elements(locator, timeout=timeout, index=index, relative=relative, raise_err=raise_err)
        if r or isinstance(r, (list, float, int)):
            return r
        if raise_err is True or (_S.raise_when_ele_not_found and raise_err is None):
            raise ElementNotFoundError(METHOD=method, ARGS={'locator': locator, 'index': index, 'timeout': timeout})

        r.method = method
        r.args = {'locator': locator, 'index': index, 'timeout': timeout}
        return r

    @property
    def timeout(self):
        return self.owner.timeout if self.owner else 10

    @property
    def child_count(self):
        return int(self._ele('xpath:count(./*)'))

    # ----------------以下属性或方法由后代实现----------------
    @property
    def tag(self):
        return

    def parent(self, level_or_loc=1):
        pass

    def next(self, index=1):
        pass

    def nexts(self):
        pass


class DrissionElement(BaseElement):

    @property
    def link(self):
        return self.attr('href') or self.attr('src')

    @property
    def css_path(self):
        return self._get_ele_path(xpath=False)

    @property
    def xpath(self):
        return self._get_ele_path()

    @property
    def comments(self):
        return self.eles('xpath:.//comment()')

    def texts(self, text_node_only=False):
        texts = self.eles('xpath:/text()') if text_node_only else [x if isinstance(x, str) else x.text
                                                                   for x in self.eles('xpath:./text() | *')]
        return [format_html(x.strip(' ').rstrip('\n')) for x in texts if x and sub('[\r\n\t ]', '', x) != '']

    def parent(self, level_or_loc=1, index=1, timeout=None):
        if isinstance(level_or_loc, int):
            loc = f'xpath:./ancestor::*[{level_or_loc}]'

        elif isinstance(level_or_loc, (tuple, str)):
            loc = get_loc(level_or_loc, True)
            if loc[0] == 'css selector':
                raise LocatorError(_S._lang.UNSUPPORTED_CSS_SYNTAX)
            loc = f'xpath:./ancestor::{loc[1].lstrip(". / ")}[{index}]'

        else:
            raise ValueError(_S._lang.join(_S._lang.INCORRECT_TYPE_, 'level_or_loc', ALLOW_TYPE='tuple, int, str',
                                           CURR_VAL=level_or_loc))

        return self._ele(loc, timeout=timeout, relative=True, raise_err=False, method='parent()')

    def child(self, locator='', index=1, timeout=None, ele_only=True):
        if isinstance(locator, int):
            index = locator
            locator = ''
        if not locator:
            loc = '*' if ele_only else 'node()'
        else:
            loc = get_loc(locator, True)  # 把定位符转换为xpath
            if loc[0] == 'css selector':
                raise LocatorError(_S._lang.UNSUPPORTED_CSS_SYNTAX)
            loc = loc[1].lstrip('./')

        node = self._ele(f'xpath:./{loc}', timeout=timeout, index=index, relative=True, raise_err=False)
        return node if node else NoneElement(self.owner, 'child()',
                                             {'locator': locator, 'index': index, 'ele_only': ele_only})

    def prev(self, locator='', index=1, timeout=None, ele_only=True):
        return self._get_relative('prev()', 'preceding', True, locator, index, timeout, ele_only)

    def next(self, locator='', index=1, timeout=None, ele_only=True):
        return self._get_relative('next()', 'following', True, locator, index, timeout, ele_only)

    def before(self, locator='', index=1, timeout=None, ele_only=True):
        return self._get_relative('before()', 'preceding', False, locator, index, timeout, ele_only)

    def after(self, locator='', index=1, timeout=None, ele_only=True):
        return self._get_relative('after()', 'following', False, locator, index, timeout, ele_only)

    def children(self, locator='', timeout=None, ele_only=True):
        if not locator:
            loc = '*' if ele_only else 'node()'
        else:
            loc = get_loc(locator, True)  # 把定位符转换为xpath
            if loc[0] == 'css selector':
                raise LocatorError(_S._lang.UNSUPPORTED_CSS_SYNTAX)
            loc = loc[1].lstrip('./')

        loc = f'xpath:./{loc}'
        nodes = self._ele(loc, timeout=timeout, index=None, relative=True)
        return [e for e in nodes if not (isinstance(e, str) and sub('[ \n\t\r]', '', e) == '')]

    def prevs(self, locator='', timeout=None, ele_only=True):
        return self._get_relatives(locator=locator, direction='preceding', timeout=timeout, ele_only=ele_only)

    def nexts(self, locator='', timeout=None, ele_only=True):
        return self._get_relatives(locator=locator, direction='following', timeout=timeout, ele_only=ele_only)

    def befores(self, locator='', timeout=None, ele_only=True):
        return self._get_relatives(locator=locator, direction='preceding',
                                   brother=False, timeout=timeout, ele_only=ele_only)

    def afters(self, locator='', timeout=None, ele_only=True):
        return self._get_relatives(locator=locator, direction='following',
                                   brother=False, timeout=timeout, ele_only=ele_only)

    def _get_relative(self, func, direction, brother, locator='', index=1, timeout=None, ele_only=True):
        if isinstance(locator, int):
            index = locator
            locator = ''
        node = self._get_relatives(index, locator, direction, brother, timeout, ele_only)
        return node if node else NoneElement(self.owner, func,
                                             {'locator': locator, 'index': index, 'ele_only': ele_only})

    def _get_relatives(self, index=None, locator='', direction='following', brother=True, timeout=.5, ele_only=True):
        brother = '-sibling' if brother else ''

        if not locator:
            loc = '*' if ele_only else 'node()'

        else:
            loc = get_loc(locator, True)  # 把定位符转换为xpath
            if loc[0] == 'css selector':
                raise LocatorError(_S._lang.UNSUPPORTED_CSS_SYNTAX)
            loc = loc[1].lstrip('./')

        loc = f'xpath:./{direction}{brother}::{loc}'

        if index is not None:
            index = index if direction == 'following' else -index
        nodes = self._ele(loc, timeout=timeout, index=index, relative=True, raise_err=False)
        if isinstance(nodes, list):
            nodes = [e for e in nodes if not (isinstance(e, str) and sub('[ \n\t\r]', '', e) == '')]
        return nodes

    # ----------------以下属性或方法由后代实现----------------
    @property
    def attrs(self):
        return

    @property
    def text(self):
        return

    @property
    def raw_text(self):
        return

    @abstractmethod
    def attr(self, name):
        return ''

    def _get_ele_path(self, xpath=True):
        return ''

    def _find_elements(self, locator, timeout, index=1, relative=False, raise_err=None):
        pass


class BasePage(BaseParser):

    def __init__(self):
        self._url = None
        self._url_available = None
        self.retry_times = 3
        self.retry_interval = 2
        self._downloader = None
        self._download_path = None
        self._none_ele_return_value = False
        self._none_ele_value = None
        self._session = None
        self._headers = None
        self._session_options = None
        self._type = 'BasePage'

    @property
    def title(self):
        ele = self._ele('xpath://title', raise_err=False, method='title')
        return ele.text if ele else None

    @property
    def url_available(self):
        return self._url_available

    @property
    def download_path(self):
        return self._download_path

    @property
    def download(self):
        if self._downloader is None:
            if not self._session:
                self._create_session()
            self._downloader = DrissionGet(driver=self, save_path=self.download_path)
        return self._downloader

    def _before_connect(self, url, retry, interval):
        is_file = False
        if isinstance(url, Path) or ('://' not in url and ':\\\\' not in url):
            p = Path(url)
            if p.exists():
                url = str(p.absolute())
                is_file = True

        self._url = url if is_file else quote(url, safe='-_.~!*\'"();:@&=+$,/\\?#[]%')
        retry = retry if retry is not None else self.retry_times
        interval = interval if interval is not None else self.retry_interval
        return retry, interval, is_file

    def _set_session_options(self, session_or_options=None):
        if not session_or_options:
            self._session_options = SessionOptions(session_or_options)

        elif isinstance(session_or_options, SessionOptions):
            self._session_options = session_or_options

        elif isinstance(session_or_options, Session):
            self._session_options = SessionOptions()
            self._session = copy(session_or_options)
            self._headers = self._session.headers
            self._session.headers = None

    def _create_session(self):
        if not self._session_options:
            self._set_session_options()
        self._session, self._headers = self._session_options.make_session()

    # ----------------以下属性或方法由后代实现----------------
    @property
    def url(self):
        return

    @property
    def json(self):
        return

    @property
    def user_agent(self):
        return

    @abstractmethod
    def get(self, url, show_errmsg=False, retry=None, interval=None):
        pass

    def _ele(self, locator, timeout=None, index=1, raise_err=None, method=None):
        if not locator:
            raise ElementNotFoundError(METHOD=method, ARGS={'locator': locator, 'index': index, 'timeout': timeout})
        if timeout is None:
            timeout = self.timeout

        r = self._find_elements(locator, timeout=timeout, index=index, raise_err=raise_err)
        if r or isinstance(r, list):
            return r
        if raise_err is True or (_S.raise_when_ele_not_found and raise_err is None):
            raise ElementNotFoundError(METHOD=method, ARGS={'locator': locator, 'index': index, 'timeout': timeout})

        r.method = method
        r.args = {'locator': locator, 'index': index, 'timeout': timeout}
        return r


================================================
FILE: DrissionPage/_base/base.pyi
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from abc import abstractmethod
from typing import Union, Tuple, List, Any, Optional, Dict

from DrissionGet import DrissionGet
from requests import Session
from requests.structures import CaseInsensitiveDict

from .._configs.session_options import SessionOptions
from .._elements.chromium_element import ChromiumElement
from .._elements.none_element import NoneElement
from .._elements.session_element import SessionElement
from .._functions.elements import SessionElementsList
from .._pages.chromium_frame import ChromiumFrame
from .._pages.chromium_page import ChromiumPage
from .._pages.session_page import SessionPage
from .._pages.web_page import WebPage


class BaseParser(object):
    """所有页面、元素类的基类"""
    _type: str
    timeout: float

    def __call__(self, locator: Union[Tuple[str, str], str], index: int = 1): ...

    def ele(self,
            locator: Union[Tuple[str, str], str, BaseElement],
            index: int = 1,
            timeout: float = None): ...

    def eles(self, locator: Union[Tuple[str, str], str], timeout=None): ...

    def find(self,
             locators: Union[str, List[str], tuple],
             any_one: bool = True,
             first_ele: bool = True,
             timeout: float = None) -> Union[Dict[str, ChromiumElement], Dict[str, SessionElement],
    Dict[str, List[ChromiumElement]], Dict[str, List[SessionElement]], Tuple[str, SessionElement],
    Tuple[str, ChromiumElement]]:
        """传入多个定位符,获取多个ele
        :param locators: 定位符组成的列表
        :param any_one: 是否任何一个定位符找到结果即返回
        :param first_ele: 每个定位符是否只获取第一个元素
        :param timeout: 超时时间(秒)
        :return: any_one为True时,返回一个找到的元素定位符和对象组成的元组,格式:(loc, ele),全都没找到返回(None, None)
                 any_one为False时,返回dict格式,key为定位符,value为找到的元素或列表
        """
        ...

    # ----------------以下属性或方法待后代实现----------------
    @property
    def html(self) -> str: ...

    def s_ele(self,
              locator: Union[Tuple[str, str], str, BaseElement, None] = None,
              index: int = 1) -> SessionElement: ...

    def s_eles(self, locator: Union[Tuple[str, str], str]) -> SessionElementsList: ...

    def _ele(self,
             locator: Union[Tuple[str, str], str],
             timeout: float = None,
             index: Optional[int] = 1,
             raise_err: bool = None,
             method: str = None): ...

    def _find_elements(self,
                       locator: Union[Tuple[str, str], str],
                       timeout: float,
                       index: Optional[int] = 1,
                       relative: bool = False,
                       raise_err: bool = None): ...


class BaseElement(BaseParser):
    """各元素类的基类"""
    owner: BasePage = ...

    def __init__(self, owner: BasePage = None): ...

    @property
    def timeout(self) -> float:
        """返回其查找元素时超时时间"""
        ...

    @property
    def child_count(self) -> int:
        """返回直接子元素的个数"""
        ...

    # ----------------以下属性或方法由后代实现----------------
    @property
    def tag(self) -> str: ...

    def parent(self, level_or_loc: Union[tuple, str, int] = 1): ...

    def prev(self, index: int = 1) -> None: ...

    def prevs(self) -> None: ...

    def next(self, index: int = 1): ...

    def nexts(self): ...

    def get_frame(self, loc_or_ind, timeout=None) -> ChromiumFrame:
        """获取元素中一个frame对象
        :param loc_or_ind: 定位符、iframe序号,序号从1开始,可传入负数获取倒数第几个
        :param timeout: 查找元素超时时间(秒)
        :return: ChromiumFrame对象
        """
        ...

    def _ele(self,
             locator: Union[Tuple[str, str], str],
             timeout: float = None,
             index: Optional[int] = 1,
             relative: bool = False,
             raise_err: bool = None,
             method: str = None):
        """调用获取元素的方法
        :param locator: 定位符
        :param timeout: 超时时间(秒)
        :param index: 获取第几个,从1开始,可传入负数获取倒数第几个
        :param relative: 是否相对定位
        :param raise_err: 找不到时是否抛出异常
        :param method: 调用的方法名
        :return: 元素对象或它们组成的列表
        """
        ...


class DrissionElement(BaseElement):
    """ChromiumElement 和 SessionElement的基类,但不是ShadowRoot的基类"""

    def __init__(self, owner: BasePage = None): ...

    @property
    def link(self) -> str:
        """返回href或src绝对url"""
        ...

    @property
    def css_path(self) -> str:
        """返回css path路径"""
        ...

    @property
    def xpath(self) -> str:
        """返回xpath路径"""
        ...

    @property
    def comments(self) -> list:
        """返回元素注释文本组成的列表"""
        ...

    def texts(self, text_node_only: bool = False) -> list:
        """返回元素内所有直接子节点的文本,包括元素和文本节点
        :param text_node_only: 是否只返回文本节点
        :return: 文本列表
        """
        ...

    def parent(self,
               level_or_loc: Union[tuple, str, int] = 1,
               index: int = 1,
               timeout: float = None) -> Union[DrissionElement, None]:
        """返回上面某一级父元素,可指定层数或用查询语法定位
        :param level_or_loc: 第几级父元素,1开始,或定位符
        :param index: 当level_or_loc传入定位符,使用此参数选择第几个结果,1开始
        :param timeout: 时间(秒)
        :return: 上级元素对象
        """
        ...

    def child(self,
              locator: Union[Tuple[str, str], str, int] = '',
              index: int = 1,
              timeout: float = None,
              ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]:
        """返回直接子元素元素或节点组成的列表,可用查询语法筛选
        :param locator: 用于筛选的查询语法
        :param index: 第几个查询结果,1开始
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 直接子元素或节点文本组成的列表
        """
        ...

    def prev(self,
             locator: Union[Tuple[str, str], str, int] = '',
             index: int = 1,
             timeout: float = None,
             ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]:
        """返回前面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
        :param locator: 用于筛选的查询语法
        :param index: 前面第几个查询结果,1开始
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 兄弟元素
        """
        ...

    def next(self,
             locator: Union[Tuple[str, str], str, int] = '',
             index: int = 1,
             timeout: float = None,
             ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]:
        """返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
        :param locator: 用于筛选的查询语法
        :param index: 后面第几个查询结果,1开始
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 兄弟元素
        """
        ...

    def before(self,
               locator: Union[Tuple[str, str], str, int] = '',
               index: int = 1,
               timeout: float = None,
               ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]:
        """返回前面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
        :param locator: 用于筛选的查询语法
        :param index: 前面第几个查询结果,1开始
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 本元素前面的某个元素或节点
        """
        ...

    def after(self,
              locator: Union[Tuple[str, str], str, int] = '',
              index: int = 1,
              timeout: float = None,
              ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]:
        """返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
        :param locator: 用于筛选的查询语法
        :param index: 后面第几个查询结果,1开始
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 本元素后面的某个元素或节点
        """
        ...

    def children(self,
                 locator: Union[Tuple[str, str], str] = '',
                 timeout: float = None,
                 ele_only: bool = True) -> List[Union[DrissionElement, str]]:
        """返回直接子元素元素或节点组成的列表,可用查询语法筛选
        :param locator: 用于筛选的查询语法
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 直接子元素或节点文本组成的列表
        """
        ...

    def prevs(self,
              locator: Union[Tuple[str, str], str] = '',
              timeout: float = None,
              ele_only: bool = True) -> List[Union[DrissionElement, str]]:
        """返回前面全部兄弟元素或节点组成的列表,可用查询语法筛选
        :param locator: 用于筛选的查询语法
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 兄弟元素或节点文本组成的列表
        """
        ...

    def nexts(self,
              locator: Union[Tuple[str, str], str] = '',
              timeout: float = None,
              ele_only: bool = True) -> List[Union[DrissionElement, str]]:
        """返回后面全部兄弟元素或节点组成的列表,可用查询语法筛选
        :param locator: 用于筛选的查询语法
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 兄弟元素或节点文本组成的列表
        """
        ...

    def befores(self,
                locator: Union[Tuple[str, str], str] = '',
                timeout: float = None,
                ele_only: bool = True) -> List[Union[DrissionElement, str]]:
        """返回后面全部兄弟元素或节点组成的列表,可用查询语法筛选
        :param locator: 用于筛选的查询语法
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 本元素前面的元素或节点组成的列表
        """
        ...

    def afters(self,
               locator: Union[Tuple[str, str], str] = '',
               timeout: float = None,
               ele_only: bool = True) -> List[Union[DrissionElement, str]]:
        """返回前面全部兄弟元素或节点组成的列表,可用查询语法筛选
        :param locator: 用于筛选的查询语法
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 本元素后面的元素或节点组成的列表
        """
        ...

    def _get_relative(self,
                      func: str,
                      direction: str,
                      brother: bool,
                      locator: Union[Tuple[str, str], str] = '',
                      index: int = 1,
                      timeout: float = None,
                      ele_only: bool = True) -> DrissionElement:
        """获取一个亲戚元素或节点,可用查询语法筛选,可指定返回筛选结果的第几个
        :param func: 方法名称
        :param direction: 方向,'following' 或 'preceding'
        :param locator: 用于筛选的查询语法
        :param index: 前面第几个查询结果,1开始
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 本元素前面的某个元素或节点
        """
        ...

    def _get_relatives(self,
                       index: int = None,
                       locator: Union[Tuple[str, str], str] = '',
                       direction: str = 'following',
                       brother: bool = True,
                       timeout: float = 0.5,
                       ele_only: bool = True) -> List[Union[DrissionElement, str]]:
        """按要求返回兄弟元素或节点组成的列表
        :param index: 获取第几个,该参数不为None时只获取该编号的元素
        :param locator: 用于筛选的查询语法
        :param direction: 'following' 或 'preceding',查找的方向
        :param brother: 查找范围,在同级查找还是整个dom前后查找
        :param timeout: 查找等待时间(秒)
        :return: 元素对象或字符串
        """
        ...

    # ----------------以下属性或方法由后代实现----------------
    @property
    def attrs(self) -> dict: ...

    @property
    def text(self) -> str: ...

    @property
    def raw_text(self) -> str: ...

    @abstractmethod
    def attr(self, name: str) -> str: ...

    def _get_ele_path(self, xpath: bool = True) -> str: ...


class BasePage(BaseParser):
    """页面类的基类"""

    _url_available: Optional[bool] = ...
    retry_times: int = ...
    retry_interval: float = ...
    _download_path: Optional[str] = ...
    _downloader: Optional[DrissionGet] = ...
    _none_ele_return_value: bool = ...
    _none_ele_value: Any = ...
    _page: Union[ChromiumPage, SessionPage, WebPage] = ...
    _session: Optional[Session] = ...
    _headers: Optional[CaseInsensitiveDict] = ...
    _session_options: Optional[SessionOptions] = ...

    def __init__(self): ...

    @property
    def title(self) -> Union[str, None]:
        """返回网页title"""
        ...

    @property
    def url_available(self) -> bool:
        """返回当前访问的url有效性"""
        ...

    @property
    def download_path(self) -> str:
        """返回默认下载路径"""
        ...

    @property
    def download(self) -> DrissionGet:
        """返回下载器对象"""
        ...

    def _before_connect(self, url: str, retry: int, interval: float) -> tuple:
        """连接前的准备
        :param url: 要访问的url
        :param retry: 重试次数
        :param interval: 重试间隔
        :return: 重试次数、间隔、是否文件组成的tuple
        """
        ...

    def _set_session_options(self, session_or_options: Union[Session, SessionOptions] = None) -> None:
        """启动配置
        :param session_or_options: Session、SessionOptions对象
        :return: None
        """
        ...

    def _create_session(self) -> None:
        """创建内建Session对象"""
        ...

    # ----------------以下属性或方法由后代实现----------------
    @property
    def url(self) -> str: ...

    @property
    def json(self) -> dict: ...

    @property
    def user_agent(self) -> str: ...

    @abstractmethod
    def get(self, url: str, show_errmsg: bool = False, retry: int = None, interval: float = None): ...

    def _ele(self,
             locator,
             timeout: float = None,
             index: Optional[int] = 1,
             raise_err: bool = None,
             method: str = None):
        """调用获取元素的方法
        :param locator: 定位符
        :param timeout: 超时时间(秒)
        :param index: 获取第几个,从1开始,可传入负数获取倒数第几个
        :param raise_err: 找不到时是否抛出异常
        :param method: 调用的方法名
        :return: 元素对象或它们组成的列表
        """
        ...


================================================
FILE: DrissionPage/_base/chromium.py
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from pathlib import Path
from re import match
from shutil import rmtree
from threading import Lock
from time import sleep, perf_counter

from requests import Session
from websocket import WebSocketBadStatusException

from .driver import BrowserDriver, Driver
from .._configs.chromium_options import ChromiumOptions
from .._functions.browser import connect_browser
from .._functions.cookies import CookiesList
from .._functions.settings import Settings as _S
from .._functions.tools import PortFinder, raise_error
from .._pages.chromium_base import Timeout
from .._pages.chromium_tab import ChromiumTab
from .._pages.mix_tab import MixTab
from .._units.downloader import DownloadManager
from .._units.setter import BrowserSetter
from .._units.states import BrowserStates
from .._units.waiter import BrowserWaiter
from ..errors import BrowserConnectError, CDPError, PageDisconnectedError, IncorrectURLError

__ERROR__ = 'error'


class Chromium(object):
    _BROWSERS = {}
    _lock = Lock()

    def __new__(cls, addr_or_opts=None, session_options=None):
        opt = handle_options(addr_or_opts)

        with cls._lock:
            is_headless, browser_id, is_exists, ws_only, driver = run_browser(opt)
            if browser_id in cls._BROWSERS:
                return cls._BROWSERS[browser_id]
        r = object.__new__(cls)
        driver.owner = r
        r._driver = driver
        r._chromium_options = opt
        r._is_headless = is_headless
        r._is_exists = is_exists
        r._ws_only = ws_only
        r.id = browser_id
        cls._BROWSERS[browser_id] = r
        return r

    def __init__(self, addr_or_opts=None, session_options=None):
        if hasattr(self, '_created'):
            return
        self._created = True

        self._type = 'Chromium'
        self._frames = {}
        self._drivers = {}
        self._all_drivers = {}
        self._relation = {}
        self._newest_tab_id = None

        self._set = None
        self._wait = None
        self._states = None
        self._timeouts = Timeout(**self._chromium_options.timeouts)
        self._load_mode = self._chromium_options.load_mode
        self._download_path = str(Path(self._chromium_options.download_path).absolute())
        self._auto_handle_alert = None
        self._none_ele_return_value = False
        self._none_ele_value = None
        self.retry_times = self._chromium_options.retry_times
        self.retry_interval = self._chromium_options.retry_interval
        self.address = self._chromium_options.address
        self._ws_address = (self._chromium_options.ws_address if self._chromium_options.ws_address
                            else f'ws://{self.address}/devtools/browser/{self.id}')
        self._disconnect_flag = False

        if (not self._ws_only
                and (not self._chromium_options._ua_set and self._is_headless != self._chromium_options.is_headless)
                or (self._is_exists and self._chromium_options._new_env)):
            self.quit(3, True)
            connect_browser(self._chromium_options)
            s = Session()
            s.trust_env = False
            s.keep_alive = False
            ws = s.get(f'http://{self.address}/json/version', headers={'Connection': 'close'})
            self.id = ws.json()['webSocketDebuggerUrl'].split('/')[-1]
            self._driver = BrowserDriver(self.id, self._ws_address, self)
            ws.close()
            s.close()
            self._is_exists = False
            self._frames = {}
            self._drivers = {}
            self._all_drivers = {}

        self.version = self._run_cdp('Browser.getVersion')['product']

        self._process_id = None
        try:
            r = self._run_cdp('SystemInfo.getProcessInfo')
            for i in r.get('processInfo', []):
                if i['type'] == 'browser':
                    self._process_id = i['id']
                    break
        except:
            pass

        self._run_cdp('Target.setDiscoverTargets', discover=True)
        self._driver.set_callback('Target.targetDestroyed', self._onTargetDestroyed)
        self._driver.set_callback('Target.targetCreated', self._onTargetCreated)
        self._dl_mgr = DownloadManager(self)

        self._session_options = session_options

    @property
    def user_data_path(self):
        return self._chromium_options.user_data_path

    @property
    def process_id(self):
        return self._process_id

    @property
    def timeout(self):
        return self._timeouts.base

    @property
    def timeouts(self):
        return self._timeouts

    @property
    def load_mode(self):
        return self._load_mode

    @property
    def download_path(self):
        return self._download_path

    @property
    def set(self):
        if self._set is None:
            self._set = BrowserSetter(self)
        return self._set

    @property
    def states(self):
        if self._states is None:
            self._states = BrowserStates(self)
        return self._states

    @property
    def wait(self):
        if self._wait is None:
            self._wait = BrowserWaiter(self)
        return self._wait

    @property
    def tabs_count(self):
        j = self._run_cdp('Target.getTargets')['targetInfos']  # 不要改用get,避免卡死
        return len([i for i in j if i['type'] in ('page', 'webview') and not i['url'].startswith('devtools://')])

    @property
    def tab_ids(self):
        if self._ws_only:
            return [i['targetId'] for i in self._run_cdp('Target.getTargets')['targetInfos']
                    if i['type'] in ('page', 'webview') and not i['url'].startswith('devtools://')]
        else:
            return [i['id'] for i in self._driver.get(f'http://{self.address}/json').json()
                    if i['type'] in ('page', 'webview') and not i['url'].startswith('devtools://')]

    @property
    def latest_tab(self):
        return self._get_tab(id_or_num=self.tab_ids[0], as_id=not _S.singleton_tab_obj)

    def cookies(self, all_info=False):
        cks = self._run_cdp(f'Storage.getCookies')['cookies']
        r = cks if all_info else [{'name': c['name'], 'value': c['value'], 'domain': c['domain']} for c in cks]
        return CookiesList(r)

    def new_tab(self, url=None, new_window=False, background=False, new_context=False):
        return self._new_tab(True, url=url, new_window=new_window, background=background, new_context=new_context)

    def get_tab(self, id_or_num=None, title=None, url=None, tab_type='page'):
        t = self._get_tab(id_or_num=id_or_num, title=title, url=url, tab_type=tab_type, mix=True, as_id=False)
        if t._type != 'MixTab':
            raise RuntimeError(_S._lang.join(_S._lang.TAB_OBJ_EXISTS))
        return t

    def get_tabs(self, title=None, url=None, tab_type='page'):
        return self._get_tabs(title=title, url=url, tab_type=tab_type, mix=True, as_id=False)

    def close_tabs(self, tabs_or_ids, others=False):
        if isinstance(tabs_or_ids, str):
            tabs = {tabs_or_ids}
        elif isinstance(tabs_or_ids, ChromiumTab):
            tabs = {tabs_or_ids.tab_id}
        elif isinstance(tabs_or_ids, (list, tuple)):
            tabs = set(i.tab_id if isinstance(i, ChromiumTab) else i for i in tabs_or_ids)
        else:
            raise ValueError(_S._lang.join(_S._lang.INCORRECT_TYPE_, 'tabs_or_ids',
                                           ALLOW_TYPE=_S._lang.TAB_OR_ID, CURR_VAL=tabs_or_ids))

        all_tabs = set(self.tab_ids)
        if others:
            tabs = all_tabs - tabs

        if len(all_tabs - tabs) > 0:
            for tab in tabs:
                self._close_tab(tab=tab)
        else:
            self.quit()

    def _close_tab(self, tab):
        if isinstance(tab, str):
            tab = self.get_tab(tab)
        tab._run_cdp('Target.closeTarget', targetId=tab.tab_id)
        while tab.driver.is_running and tab.tab_id in self._all_drivers:
            sleep(.01)

    def activate_tab(self, id_ind_tab):
        if isinstance(id_ind_tab, int):
            id_ind_tab += -1 if id_ind_tab else 1
            id_ind_tab = self.tab_ids[id_ind_tab]
        elif isinstance(id_ind_tab, ChromiumTab):
            id_ind_tab = id_ind_tab.tab_id
        self._run_cdp('Target.activateTarget', targetId=id_ind_tab)

    def reconnect(self):
        self._disconnect_flag = True
        self._driver.stop()
        BrowserDriver.BROWSERS.pop(self.id)
        self._driver = BrowserDriver(self.id, self._ws_address, self)
        self._run_cdp('Target.setDiscoverTargets', discover=True)
        self._driver.set_callback('Target.targetDestroyed', self._onTargetDestroyed)
        self._driver.set_callback('Target.targetCreated', self._onTargetCreated)
        self._disconnect_flag = False

    def clear_cache(self, cache=True, cookies=True):
        if cache:
            self.latest_tab.run_cdp('Network.clearBrowserCache')

        if cookies:
            self._run_cdp('Storage.clearCookies')

    def quit(self, timeout=5, force=False, del_data=False):
        try:
            self._run_cdp('Browser.close')
        except PageDisconnectedError:
            pass
        self._driver.stop()

        drivers = list(self._all_drivers.values())
        for tab in drivers:
            for driver in tab:
                driver.stop()
        if not self.address.startswith('127.0.0.1'):
            return

        if force:
            pids = None
            try:
                pids = [pid['id'] for pid in self._run_cdp('SystemInfo.getProcessInfo')['processInfo']]
            except:
                pass

            if pids:
                from psutil import Process
                for pid in pids:
                    try:
                        Process(pid).kill()
                    except:
                        pass

                from os import popen
                from platform import system
                end_time = perf_counter() + timeout
                while perf_counter() < end_time:
                    ok = True
                    for pid in pids:
                        txt = f'tasklist | findstr {pid}' if system().lower() == 'windows' else f'ps -ef | grep {pid}'
                        p = popen(txt)
                        sleep(.05)
                        try:
                            if f'  {pid} ' in p.read():
                                ok = False
                                break
                        except TypeError:
                            pass

                    if ok:
                        break

        if del_data and not self._chromium_options.is_auto_port and self._chromium_options.user_data_path:
            path = Path(self._chromium_options.user_data_path)
            rmtree(path, True)

    def _new_tab(self, mix=True, url=None, new_window=False, background=False, new_context=False):
        tab_type = MixTab if mix else ChromiumTab
        tab = None
        if new_context:
            tab = self._run_cdp('Target.createBrowserContext')['browserContextId']

        kwargs = {'url': ''}
        if new_window:
            kwargs['newWindow'] = True
        if background:
            kwargs['background'] = True
        if tab:
            kwargs['browserContextId'] = tab

        if self.states.is_incognito and not new_context:
            return _new_tab_by_js(self, url, tab_type, new_window)
        else:
            try:
                tab = self._run_cdp('Target.createTarget', **kwargs)['targetId']
            except CDPError:
                return _new_tab_by_js(self, url, tab_type, new_window)

        while self.states.is_alive:
            if tab in self._drivers:
                break
            sleep(.01)
        else:
            raise BrowserConnectError(_S._lang.BROWSER_DISCONNECTED)
        tab = tab_type(self, tab)
        if url:
            tab.get(url)
        return tab

    def _get_tab(self, id_or_num=None, title=None, url=None, tab_type='page', mix=True, as_id=False):
        if id_or_num is not None:
            if isinstance(id_or_num, int):
                id_or_num = self.tab_ids[id_or_num - 1 if id_or_num > 0 else id_or_num]
            elif isinstance(id_or_num, ChromiumTab):
                return id_or_num.tab_id if as_id else ChromiumTab(self, id_or_num.tab_id)
            else:
                j = self._run_cdp('Target.getTargets')['targetInfos']
                if id_or_num not in [i['targetId'] for i in j]:
                    raise RuntimeError(_S._lang.join(_S._lang.NO_SUCH_TAB, ARG=id_or_num, ALL_TABS=self.tab_ids))

        elif title == url is None and tab_type == 'page':
            id_or_num = self.tab_ids[0]

        else:
            tabs = self._get_tabs(title=title, url=url, tab_type=tab_type, as_id=True)
            if tabs:
                id_or_num = tabs[0]
            else:
                raise RuntimeError(_S._lang.join(_S._lang.NO_SUCH_TAB,
                                                 ARGS={'id_or_num': id_or_num, 'title': title, 'url': url,
                                                       'tab_type': tab_type}))

        if as_id:
            return id_or_num
        with self._lock:
            return MixTab(self, id_or_num) if mix else ChromiumTab(self, id_or_num)

    def _get_tabs(self, title=None, url=None, tab_type='page', mix=True, as_id=False):
        if self._ws_only:
            tabs = self._run_cdp('Target.getTargets')['targetInfos']
            _id = 'targetId'
        else:
            tabs = self._driver.get(f'http://{self.address}/json').json()  # 不要改用cdp
            _id = 'id'

        if isinstance(tab_type, str):
            tab_type = {tab_type}
        elif isinstance(tab_type, (list, tuple, set)):
            tab_type = set(tab_type)
        elif tab_type is not None:
            raise ValueError(_S._lang.join(_S._lang.INCORRECT_TYPE_, 'tab_type',
                                           ALLOW_TYPE='set, list, tuple, str, None', CURR_VAL=tab_type))

        tabs = [i for i in tabs if ((title is None or title in i['title']) and (url is None or url in i['url'])
                                    and (tab_type is None or i['type'] in tab_type)
                                    and i['title'] != 'chrome-extension://neajdppkdcdipfabeoofebfddakdcjhd/audio.html')]
        if as_id:
            return [tab[_id] for tab in tabs]
        with self._lock:
            if mix:
                return [MixTab(self, tab[_id]) for tab in tabs]
            else:
                return [ChromiumTab(self, tab[_id]) for tab in tabs]

    def _run_cdp(self, cmd, **cmd_args):
        ignore = cmd_args.pop('_ignore', None)
        r = self._driver.run(cmd, **cmd_args)
        return r if __ERROR__ not in r else raise_error(r, self, ignore)

    def _get_driver(self, tab_id, owner=None):
        d = self._drivers.pop(tab_id, None)
        if not d:
            if self._ws_only:
                d = Driver(tab_id, self._ws_address)
                d.session_id = d.run('Target.attachToTarget', targetId=tab_id, flatten=True)['sessionId']
            else:
                d = Driver(tab_id, f'ws://{self.address}/devtools/page/{tab_id}')
        d.owner = owner
        self._all_drivers.setdefault(tab_id, set()).add(d)
        return d

    def _onTargetCreated(self, **kwargs):
        if (kwargs['targetInfo']['type'] in ('page', 'webview')
                and kwargs['targetInfo']['targetId'] not in self._all_drivers
                and not kwargs['targetInfo']['url'].startswith('devtools://')):
            try:
                tab_id = kwargs['targetInfo']['targetId']
                self._frames[tab_id] = tab_id
                if self._ws_only:
                    d = Driver(tab_id, self._ws_address)
                    d.session_id = d.run('Target.attachToTarget', targetId=tab_id, flatten=True)['sessionId']
                else:
                    d = Driver(tab_id, f'ws://{self.address}/devtools/page/{tab_id}')
                self._relation[tab_id] = kwargs['targetInfo'].get('openerId', None)
                self._drivers[tab_id] = d
                self._all_drivers.setdefault(tab_id, set()).add(d)
                self._newest_tab_id = tab_id
            except WebSocketBadStatusException:
                pass

    def _onTargetDestroyed(self, **kwargs):
        tab_id = kwargs['targetId']
        self._dl_mgr.clear_tab_info(tab_id)
        for key in [k for k, i in self._frames.items() if i == tab_id]:
            self._frames.pop(key, None)
        for d in self._all_drivers.get(tab_id, tuple()):
            d.stop()
        self._drivers.pop(tab_id, None)
        self._all_drivers.pop(tab_id, None)
        self._relation.pop(tab_id, None)

    def _on_disconnect(self):
        if not self._disconnect_flag:
            Chromium._BROWSERS.pop(self.id, None)
            if self._chromium_options.is_auto_port and self._chromium_options.user_data_path:
                path = Path(self._chromium_options.user_data_path)
                end_time = perf_counter() + 7
                while perf_counter() < end_time:
                    if not path.exists():
                        break
                    try:
                        rmtree(path)
                        break
                    except (PermissionError, FileNotFoundError, OSError):
                        pass
                    sleep(.03)


def handle_options(addr_or_opts):
    if not addr_or_opts:
        _chromium_options = ChromiumOptions(addr_or_opts)
        if _chromium_options.is_auto_port:
            port, path = PortFinder(_chromium_options.tmp_path).get_port(_chromium_options.is_auto_port)
            _chromium_options._address = f'127.0.0.1:{port}'
            _chromium_options.set_user_data_path(path)

    elif isinstance(addr_or_opts, ChromiumOptions):
        if addr_or_opts.is_auto_port:
            port, path = PortFinder(addr_or_opts.tmp_path).get_port(addr_or_opts.is_auto_port)
            addr_or_opts._address = f'127.0.0.1:{port}'
            addr_or_opts.set_user_data_path(path)
        _chromium_options = addr_or_opts

    elif isinstance(addr_or_opts, str) and ':' in addr_or_opts:
        _chromium_options = ChromiumOptions()
        _chromium_options.set_address(addr_or_opts)

    elif isinstance(addr_or_opts, int):
        _chromium_options = ChromiumOptions()
        _chromium_options.set_local_port(addr_or_opts)

    else:
        raise ValueError(_S._lang.join(_S._lang.INCORRECT_VAL_, 'addr_or_opts',
                                       ALLOW_TYPE=_S._lang.IP_OR_OPTIONS, CURR_VAL=addr_or_opts))

    return _chromium_options


def run_browser(chromium_options):
    ws_only = False
    if chromium_options.ws_address:
        try:
            driver = BrowserDriver('', chromium_options.ws_address, None)
        except EnvironmentError:
            raise
        except Exception as e:
            raise BrowserConnectError(_S._lang.join(_S._lang.BROWSER_CONNECT_ERR2, INFO=str(e)))
        browser_id = driver.run('Target.getTargets')
        if 'error' in browser_id:
            raise BrowserConnectError(_S._lang.join(_S._lang.BROWSER_CONNECT_ERR2, INFO=browser_id['error']))
        browser_id = browser_id['targetInfos'][0]['browserContextId']
        is_headless = 'headless' in driver.run('Browser.getVersion')['userAgent'].lower()
        driver.id = browser_id
        if 'devtools/browser' not in chromium_options.ws_address:
            return is_headless, browser_id, True, True, driver

        s = Session()
        s.trust_env = False
        s.keep_alive = False
        try:
            ws = s.get(f'http://{chromium_options.address}/json/version', headers={'Connection': 'close'}, timeout=2)
            if not ws:
                ws_only = True
            else:
                ws.close()
        except:
            ws_only = True
        s.close()
        return is_headless, browser_id, True, ws_only, driver

    is_exists = connect_browser(chromium_options)
    try:
        s = Session()
        s.trust_env = False
        s.keep_alive = False
        ws = s.get(f'http://{chromium_options.address}/json/version', headers={'Connection': 'close'}, timeout=2)
        if not ws and not chromium_options.ws_address:
            raise BrowserConnectError(_S._lang.BROWSER_CONNECT_ERR2)
        json = ws.json()
        browser_id = json['webSocketDebuggerUrl'].split('/')[-1]
        is_headless = 'headless' in json['User-Agent'].lower()
        ws.close()
        s.close()
    except KeyError:
        raise BrowserConnectError(_S._lang.BROWSER_NOT_FOR_CONTROL)
    except:
        raise BrowserConnectError(_S._lang.BROWSER_CONNECT_ERR2)
    driver = BrowserDriver('', f'ws://{chromium_options.address}/devtools/browser/{browser_id}', None)
    browser_id = driver.run('Target.getTargets')
    if 'error' in browser_id:
        raise BrowserConnectError(_S._lang.join(_S._lang.BROWSER_CONNECT_ERR2, INFO=browser_id['error']))
    browser_id = browser_id['targetInfos'][0]['browserContextId']

    return is_headless, browser_id, is_exists, ws_only, driver


def _new_tab_by_js(browser: Chromium, url, tab_type, new_window):
    mix = tab_type == MixTab
    tab = browser._get_tab(mix=mix)
    if url and not match(r'^.*?://.*', url):
        raise IncorrectURLError(_S._lang.INVALID_URL, url=url)
    url = f'"{url}"' if url else '""'
    new = 'target="_new"' if new_window else 'target="_blank"'
    tid = browser._newest_tab_id
    tab.run_js(f'window.open({url}, {new})')
    tid = browser.wait.new_tab(curr_tab=tid)
    return browser._get_tab(tid, mix=mix)


================================================
FILE: DrissionPage/_base/chromium.pyi
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from threading import Lock
from typing import List, Optional, Set, Dict, Union, Tuple, Literal, Any

from .driver import BrowserDriver, Driver
from .._configs.chromium_options import ChromiumOptions
from .._configs.session_options import SessionOptions
from .._functions.cookies import CookiesList
from .._pages.chromium_base import Timeout, ChromiumBase
from .._pages.chromium_tab import ChromiumTab
from .._pages.mix_tab import MixTab
from .._units.downloader import DownloadManager
from .._units.setter import BrowserSetter
from .._units.states import BrowserStates
from .._units.waiter import BrowserWaiter


class Chromium(object):
    _BROWSERS: dict = ...
    _lock: Lock = ...

    id: str = ...
    address: str = ...
    _ws_address: str = ...
    version: str = ...
    retry_times: int = ...
    retry_interval: float = ...

    _set: Optional[BrowserSetter] = ...
    _wait: Optional[BrowserWaiter] = ...
    _states: Optional[BrowserStates] = ...
    _chromium_options: ChromiumOptions = ...
    _session_options: SessionOptions = ...
    _driver: BrowserDriver = ...
    _frames: dict = ...
    _drivers: Dict[str, Driver] = ...
    _all_drivers: Dict[str, Set[Driver]] = ...
    _relation: Dict[str, Optional[str]] = ...
    _process_id: Optional[int] = ...
    _dl_mgr: DownloadManager = ...
    _timeouts: Timeout = ...
    _load_mode: str = ...
    _download_path: str = ...
    _auto_handle_alert: Optional[bool] = ...
    _is_exists: bool = ...
    _is_headless: bool = ...
    _ws_only: bool = ...
    _disconnect_flag: bool = ...
    _none_ele_return_value: bool = ...
    _none_ele_value: Any = ...
    _newest_tab_id: Optional[str] = ...

    def __new__(cls,
                addr_or_opts: Union[str, int, ChromiumOptions] = None,
                session_options: Union[SessionOptions, None, False] = None):
        """
        :param addr_or_opts: 浏览器地址:端口、ws地址、ChromiumOptions对象或端口数字(int)
        :param session_options: 使用双模Tab时使用的默认Session配置,为None使用ini文件配置,为False不从ini读取
        """
        ...

    def __init__(self, addr_or_opts: Union[str, int, ChromiumOptions] = None,
                 session_options: Union[SessionOptions, None, False] = None):
        """
        :param addr_or_opts: 浏览器地址:端口、ws地址、ChromiumOptions对象或端口数字(int)
        :param session_options: 使用双模Tab时使用的默认Session配置,为None使用ini文件配置,为False不从ini读取
        """
        ...

    @property
    def user_data_path(self) -> str:
        """返回用户文件夹路径"""
        ...

    @property
    def process_id(self) -> Optional[int]:
        """返回浏览器进程id"""
        ...

    @property
    def timeout(self) -> float:
        """返回基础超时设置"""
        ...

    @property
    def timeouts(self) -> Timeout:
        """返回所有超时设置"""
        ...

    @property
    def load_mode(self) -> Literal['none', 'normal', 'eager']:
        """返回页面加载模式,包括 'none', 'normal', 'eager' 三种"""
        ...

    @property
    def download_path(self) -> str:
        """返回默认下载路径"""
        ...

    @property
    def set(self) -> BrowserSetter:
        """返回用于设置的对象"""
        ...

    @property
    def states(self) -> BrowserStates:
        """返回用于获取状态的对象"""
        ...

    @property
    def wait(self) -> BrowserWaiter:
        """返回用于等待的对象"""
        ...

    @property
    def tabs_count(self) -> int:
        """返回标签页数量,只统计page、webview类型"""
        ...

    @property
    def tab_ids(self) -> List[str]:
        """返回所有标签页id组成的列表,只统计page、webview类型"""
        ...

    @property
    def latest_tab(self) -> Union[MixTab, str]:
        """返回最新的标签页,最新标签页指最后创建或最后被激活的
        当Settings.singleton_tab_obj==True时返回Tab对象,否则返回tab id"""
        ...

    def cookies(self, all_info: bool = False) -> CookiesList:
        """以list格式返回所有域名的cookies
        :param all_info: 是否返回所有内容,False则只返回name, value, domain
        :return: cookies组成的列表
        """
        ...

    def new_tab(self,
                url: str = None,
                new_window: bool = False,
                background: bool = False,
                new_context: bool = False) -> MixTab:
        """新建一个标签页
        :param url: 新标签页跳转到的网址,为None时新建空标签页
        :param new_window: 是否在新窗口打开标签页,隐身模式下无效
        :param background: 是否不激活新标签页,隐身模式和访客模式及new_window为True时无效
        :param new_context: 是否创建独立环境,隐身模式和访客模式下无效
        :return: 新标签页对象
        """
        ...

    def get_tab(self,
                id_or_num: Union[str, int] = None,
                title: str = None,
                url: str = None,
                tab_type: Union[str, list, tuple] = 'page',
                as_id: bool = False) -> Union[MixTab, str]:
        """获取一个标签页对象,id_or_num不为None时,后面几个参数无效
        :param id_or_num: 要获取的标签页id或序号,序号从1开始,可传入负数获取倒数第几个,不是视觉排列顺序,而是激活顺序
        :param title: 要匹配title的文本,模糊匹配,为None则匹配所有
        :param url: 要匹配url的文本,模糊匹配,为None则匹配所有
        :param tab_type: tab类型,可用列表输入多个,如 'page', 'iframe' 等,为None则匹配所有
        :param as_id: 是否返回标签页id而不是标签页对象
        :return: Tab对象
        """
        ...

    def get_tabs(self,
                 title: str = None,
                 url: str = None,
                 tab_type: Union[str, list, tuple] = 'page',
                 as_id: bool = False) -> List[MixTab, str]:
        """查找符合条件的tab,返回它们组成的列表,title和url是与关系
        :param title: 要匹配title的文本
        :param url: 要匹配url的文本
        :param tab_type: tab类型,可用列表输入多个
        :param as_id: 是否返回标签页id而不是标签页对象
        :return: Tab对象列表
        """
        ...

    def close_tabs(self,
                   tabs_or_ids: Union[str, ChromiumTab, List[Union[str, ChromiumTab]],
                   Tuple[Union[str, ChromiumTab]]],
                   others: bool = False) -> None:
        """关闭传入的标签页,可传入多个
        :param tabs_or_ids: 指定的标签页对象或id,可用列表或元组传入多个
        :param others: 是否关闭指定标签页之外的
        :return: None
        """
        ...

    def _close_tab(self, tab: Union[ChromiumBase, str]):
        """关闭一个标签页
        :param tab: 标签页对象或id
        :return: None
        """

    def activate_tab(self, id_ind_tab: Union[int, str, ChromiumTab]) -> None:
        """使一个标签页显示到前端
        :param id_ind_tab: 标签页id(str)、Tab对象或标签页序号(int),序号从1开始
        :return: None
        """
        ...

    def reconnect(self) -> None:
        """断开重连"""
        ...

    def clear_cache(self, cache: bool = True, cookies: bool = True) -> None:
        """清除缓存,可选要清除的项
        :param cache: 是否清除cache
        :param cookies: 是否清除cookies
        :return: None
        """
        ...

    def quit(self, timeout: float = 5, force: bool = False, del_data: bool = False) -> None:
        """关闭浏览器
        :param timeout: 等待浏览器关闭超时时间(秒)
        :param force: 是否立刻强制终止进程
        :param del_data: 是否删除用户文件夹
        :return: None
        """
        ...

    def _new_tab(self,
                 mix: bool = True,
                 url: str = None,
                 new_window: bool = False,
                 background: bool = False,
                 new_context: bool = False) -> Union[ChromiumTab, MixTab]:
        """新建一个标签页
        :param mix: 是否创建MixTab
        :param url: 新标签页跳转到的网址
        :param new_window: 是否在新窗口打开标签页
        :param background: 是否不激活新标签页,如new_window为True则无效
        :param new_context: 是否创建新的上下文
        :return: 新标签页对象
        """
        ...

    def _get_tab(self,
                 id_or_num: Union[str, int] = None,
                 title: str = None,
                 url: str = None,
                 tab_type: Union[str, list, tuple] = 'page',
                 mix: bool = True,
                 as_id: bool = False) -> Union[ChromiumTab, str]:
        """获取一个标签页对象,id_or_num不为None时,后面几个参数无效
        :param id_or_num: 要获取的标签页id或序号,序号从1开始,可传入负数获取倒数第几个,不是视觉排列顺序,而是激活顺序
        :param title: 要匹配title的文本,模糊匹配,为None则匹配所有
        :param url: 要匹配url的文本,模糊匹配,为None则匹配所有
        :param tab_type: tab类型,可用列表输入多个,如 'page', 'iframe' 等,为None则匹配所有
        :param mix: 是否返回可切换模式的Tab对象
        :param as_id: 是否返回标签页id而不是标签页对象,mix=False时无效
        :return: Tab对象
        """
        ...

    def _get_tabs(self,
                  title: str = None,
                  url: str = None,
                  tab_type: Union[str, list, tuple] = 'page',
                  mix: bool = True,
                  as_id: bool = False) -> List[ChromiumTab, str]:
        """查找符合条件的tab,返回它们组成的列表,title和url是与关系
        :param title: 要匹配title的文本
        :param url: 要匹配url的文本
        :param tab_type: tab类型,可用列表输入多个
        :param mix: 是否返回可切换模式的Tab对象
        :param as_id: 是否返回标签页id而不是标签页对象,mix=False时无效
        :return: Tab对象列表
        """
        ...

    def _run_cdp(self, cmd, **cmd_args) -> dict:
        """执行Chrome DevTools Protocol语句
        :param cmd: 协议项目
        :param cmd_args: 参数
        :return: 执行的结果
        """
        ...

    def _get_driver(self, tab_id: str, owner=None) -> Driver:
        """新建并返回指定tab id的Driver
        :param tab_id: 标签页id
        :param owner: 使用该驱动的对象
        :return: Driver对象
        """
        ...

    def _onTargetCreated(self, **kwargs): ...

    def _onTargetDestroyed(self, **kwargs): ...

    def _on_disconnect(self): ...


def handle_options(addr_or_opts):
    """设置浏览器启动属性
    :param addr_or_opts: 'ip:port'、ChromiumOptions、Driver
    :return: 返回ChromiumOptions对象
    """
    ...


def run_browser(chromium_options)->Tuple[bool, str, bool, bool, BrowserDriver]:
    """连接浏览器
    :param chromium_options: ChromiumOptions对象
    :return: 返回(是否无头, 浏览器id, 是否接管已存在, 是否只能用ws连接, 浏览器连接驱动)
    """
    ...


================================================
FILE: DrissionPage/_base/driver.py
================================================
# -*- coding: utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from json import dumps, loads, JSONDecodeError
from queue import Queue, Empty
from threading import Thread
from time import perf_counter, sleep

from requests import Session
from requests import adapters
from websocket import (WebSocketTimeoutException, WebSocketConnectionClosedException, create_connection,
                       WebSocketException, WebSocketBadStatusException)

from .._functions.settings import Settings as _S
from ..errors import PageDisconnectedError, BrowserConnectError

adapters.DEFAULT_RETRIES = 5


class Driver(object):
    def __init__(self, _id, address, owner=None):
        self.id = _id
        self.address = address
        self.owner = owner
        self.alert_flag = False  # 标记alert出现,跳过一条请求后复原

        self._cur_id = 0
        self._ws = None

        self._recv_th = Thread(target=self._recv_loop)
        self._handle_event_th = Thread(target=self._handle_event_loop)
        self._recv_th.daemon = True
        self._handle_event_th.daemon = True
        self._handle_immediate_event_th = None

        self.is_running = False
        self.session_id = None

        self.event_handlers = {}
        self.immediate_event_handlers = {}
        self.method_results = {}
        self.event_queue = Queue()
        self.immediate_event_queue = Queue()

        self.start()

    def _send(self, message, timeout=None):
        self._cur_id += 1
        ws_id = self._cur_id
        message['id'] = ws_id
        message_json = dumps(message)

        end_time = perf_counter() + timeout if timeout is not None else None
        self.method_results[ws_id] = Queue()
        try:
            self._ws.send(message_json)
            if timeout == 0:
                self.method_results.pop(ws_id, None)
                return {'id': ws_id, 'result': {}}

        except (OSError, WebSocketConnectionClosedException):
            self.method_results.pop(ws_id, None)
            return {'error': {'message': 'connection disconnected'}, 'type': 'connection_error'}

        while self.is_running:
            try:
                result = self.method_results[ws_id].get(timeout=.2)
                self.method_results.pop(ws_id, None)
                return result

            except Empty:
                if self.alert_flag and message['method'].startswith(('Input.', 'Runtime.')):
                    return {'error': {'message': 'alert exists.'}, 'type': 'alert_exists'}

                if timeout is not None and perf_counter() > end_time:
                    self.method_results.pop(ws_id, None)
                    return {'error': {'message': 'alert exists.'}, 'type': 'alert_exists'} \
                        if self.alert_flag else {'error': {'message': 'timeout'}, 'type': 'timeout'}

                continue

        return {'error': {'message': 'connection disconnected'}, 'type': 'connection_error'}

    def _recv_loop(self):
        while self.is_running:
            try:
                # self._ws.settimeout(1)
                msg_json = self._ws.recv()
                msg = loads(msg_json)
            except WebSocketTimeoutException:
                continue
            except (WebSocketException, OSError, WebSocketConnectionClosedException, JSONDecodeError):
                self._stop()
                return

            if 'method' in msg:
                if msg['method'].startswith('Page.javascriptDialog'):
                    self.alert_flag = msg['method'].endswith('Opening')
                function = self.immediate_event_handlers.get(msg['method'])
                if function:
                    self._handle_immediate_event(function, msg['params'])
                else:
                    self.event_queue.put(msg)

            elif msg.get('id') in self.method_results:
                self.method_results[msg['id']].put(msg)

    def _handle_event_loop(self):
        while self.is_running:
            try:
                event = self.event_queue.get(timeout=1)
            except Empty:
                continue

            function = self.event_handlers.get(event['method'])
            if function:
                function(**event['params'])

            self.event_queue.task_done()

    def _handle_immediate_event_loop(self):
        while not self.immediate_event_queue.empty():
            function, kwargs = self.immediate_event_queue.get(timeout=1)
            try:
                function(**kwargs)
            except PageDisconnectedError:
                pass

    def _handle_immediate_event(self, function, kwargs):
        self.immediate_event_queue.put((function, kwargs))
        if self._handle_immediate_event_th is None or not self._handle_immediate_event_th.is_alive():
            self._handle_immediate_event_th = Thread(target=self._handle_immediate_event_loop)
            self._handle_immediate_event_th.daemon = True
            self._handle_immediate_event_th.start()

    def run(self, _method, **kwargs):
        if not self.is_running:
            return {'error': 'connection disconnected', 'type': 'connection_error'}

        timeout = kwargs.pop('_timeout', _S.cdp_timeout)
        if self.session_id:
            result = self._send({'method': _method, 'params': kwargs, 'sessionId': self.session_id}, timeout=timeout)
        else:
            result = self._send({'method': _method, 'params': kwargs}, timeout=timeout)
        if 'result' not in result and 'error' in result:
            kwargs['_timeout'] = timeout
            return {'error': result['error']['message'], 'type': result.get('type', 'call_method_error'),
                    'method': _method, 'args': kwargs, 'data': result['error'].get('data')}
        else:
            return result['result']

    def start(self):
        self.is_running = True
        try:
            self._ws = create_connection(self.address, enable_multithread=True, suppress_origin=True)
        except WebSocketBadStatusException as e:
            if 'Handshake status 403 Forbidden' in str(e):
                raise EnvironmentError(_S._lang.join(_S._lang.UPGRADE_WS))
            else:
                raise
        except ConnectionRefusedError:
            raise BrowserConnectError(_S._lang.BROWSER_NOT_EXIST)
        self._recv_th.start()
        self._handle_event_th.start()
        return True

    def stop(self):
        self._stop()
        while self._handle_event_th.is_alive() or self._recv_th.is_alive():
            sleep(.01)
        return True

    def _stop(self):
        if not self.is_running:
            return False

        self.is_running = False
        if self._ws:
            self._ws.close()
            self._ws = None

        self.event_handlers.clear()
        self.method_results.clear()
        self.event_queue.queue.clear()

        if hasattr(self.owner, '_on_disconnect'):
            self.owner._on_disconnect()

    def set_callback(self, event, callback, immediate=False):
        handler = self.immediate_event_handlers if immediate else self.event_handlers
        if callback:
            handler[event] = callback
        else:
            handler.pop(event, None)


class BrowserDriver(Driver):
    BROWSERS = {}

    def __new__(cls, _id, address, owner):
        if address in cls.BROWSERS:
            return cls.BROWSERS[address]
        return object.__new__(cls)

    def __init__(self, _id, address, owner):
        if hasattr(self, '_created'):
            return
        self._created = True
        BrowserDriver.BROWSERS[address] = self
        super().__init__(_id, address, owner)

    def __repr__(self):
        return f'<BrowserDriver {self.id}>'

    @staticmethod
    def get(url):
        s = Session()
        s.trust_env = False
        s.keep_alive = False
        r = s.get(url, headers={'Connection': 'close'})
        r.close()
        s.close()
        return r


================================================
FILE: DrissionPage/_base/driver.pyi
================================================
# -*- coding: utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from queue import Queue
from threading import Thread
from typing import Union, Callable, Dict, Optional

from requests import Response
from websocket import WebSocket

from .._base.chromium import Chromium


class Driver(object):
    id: str
    address: str
    owner = ...
    alert_flag: bool
    _cur_id: int
    _ws: Optional[WebSocket]
    _recv_th: Thread
    _handle_event_th: Thread
    _handle_immediate_event_th: Optional[Thread]
    session_id: Optional[str] = ...
    is_running: bool
    event_handlers: dict
    immediate_event_handlers: dict
    method_results: dict
    event_queue: Queue
    immediate_event_queue: Queue

    def __init__(self, _id: str, address: str, owner=None):
        """
        :param _id: 标签页id
        :param address: 浏览器连接地址
        :param owner: 创建这个驱动的对象
        """
        ...

    def _send(self, message: dict, timeout: float = None) -> dict:
        """发送信息到浏览器,并返回浏览器返回的信息
        :param message: 发送给浏览器的数据
        :param timeout: 超时时间,为None表示无限
        :return: 浏览器返回的数据
        """
        ...

    def _recv_loop(self) -> None:
        """接收浏览器信息的守护线程方法"""
        ...

    def _handle_event_loop(self) -> None:
        """当接收到浏览器信息,执行已绑定的方法"""
        ...

    def _handle_immediate_event_loop(self): ...

    def _handle_immediate_event(self, function: Callable, kwargs: dict):
        """处理立即执行的动作
        :param function: 要运行下方法
        :param kwargs: 方法参数
        :return: None
        """
        ...

    def run(self, _method: str, **kwargs) -> dict:
        """执行cdp方法
        :param _method: cdp方法名
        :param kwargs: cdp参数
        :return: 执行结果
        """
        ...

    def start(self) -> bool:
        """启动连接"""
        ...

    def stop(self) -> bool:
        """中断连接"""
        ...

    def _stop(self) -> None:
        """中断连接"""
        ...

    def set_callback(self, event: str, callback: Union[Callable, None], immediate: bool = False) -> None:
        """绑定cdp event和回调方法
        :param event: cdp event
        :param callback: 绑定到cdp event的回调方法
        :param immediate: 是否要立即处理的动作
        :return: None
        """
        ...


class BrowserDriver(Driver):
    BROWSERS: Dict[str, Driver] = ...
    owner: Chromium = ...

    def __new__(cls, _id: str, address: str, owner: Chromium):
        """
        :param _id: 浏览器id
        :param address: 浏览器连接地址
        :param owner: 浏览器对象
        """
        ...

    def __init__(self, _id: str, address: str, owner: Optional[Chromium]):
        """
        :param _id: 浏览器id
        :param address: 浏览器连接地址
        :param owner: 浏览器对象
        """
        ...

    @staticmethod
    def get(url) -> Response:
        """
        :param url: 要访问的链接
        :return: Response对象
        """
        ...


================================================
FILE: DrissionPage/_configs/chromium_options.py
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from pathlib import Path
from re import search
from urllib.parse import urlparse

from .options_manage import OptionsManager
from .._functions.settings import Settings as _S


class ChromiumOptions(object):
    def __init__(self, read_file=True, ini_path=None):
        self._user_data_path = None
        self._user = 'Default'
        self._prefs_to_del = []
        self.clear_file_flags = False
        self._is_headless = False
        self._ua_set = False
        self.ws_address = ''

        if read_file is False:
            ini_path = False
            self.ini_path = None
        elif ini_path:
            ini_path = Path(ini_path).absolute()
            if not ini_path.exists():
                raise FileNotFoundError(_S._lang.join(_S._lang.INI_NOT_FOUND, PATH=ini_path))
            self.ini_path = str(ini_path)
        else:
            self.ini_path = str(Path(__file__).parent / 'configs.ini')

        om = OptionsManager(ini_path)
        options = om.chromium_options
        self._download_path = om.paths.get('download_path', '.') or '.'
        self._tmp_path = om.paths.get('tmp_path', None) or None
        self._arguments = options.get('arguments', [])
        self._browser_path = options.get('browser_path', '')
        self._extensions = options.get('extensions', [])
        self._prefs = options.get('prefs', {})
        self._flags = options.get('flags', {})
        self._address = options.get('address', '')
        self._load_mode = options.get('load_mode', 'normal')
        self._system_user_path = options.get('system_user_path', False)
        self._existing_only = options.get('existing_only', False)
        self._new_env = options.get('new_env', False)
        for i in self._arguments:
            if i.startswith('--headless'):
                self._is_headless = True
                break

        self._proxy = om.proxies.get('http', None) or om.proxies.get('https', None)

        user_path = user = False
        for arg in self._arguments:
            if arg.startswith('--user-data-dir='):
                self.set_user_data_path(arg[16:])
                user_path = True
            if arg.startswith('--profile-directory='):
                self.set_user(arg[20:])
                user = True
            if user and user_path:
                break

        timeouts = om.timeouts
        self._timeouts = {'base': timeouts['base'],
                          'page_load': timeouts['page_load'],
                          'script': timeouts['script']}

        self._auto_port = options.get('auto_port', False)

        others = om.others
        self._retry_times = others.get('retry_times', 3)
        self._retry_interval = others.get('retry_interval', 2)

        return

    def __repr__(self):
        return f'<ChromiumOptions at {id(self)}>'

    @property
    def download_path(self):
        return self._download_path

    @property
    def browser_path(self):
        return self._browser_path

    @property
    def user_data_path(self):
        return self._user_data_path

    @property
    def tmp_path(self):
        return self._tmp_path

    @property
    def user(self):
        return self._user

    @property
    def load_mode(self):
        return self._load_mode

    @property
    def timeouts(self):
        return self._timeouts

    @property
    def proxy(self):
        return self._proxy

    @property
    def address(self):
        return self._address

    @property
    def arguments(self):
        return self._arguments

    @property
    def extensions(self):
        return self._extensions

    @property
    def preferences(self):
        return self._prefs

    @property
    def flags(self):
        return self._flags

    @property
    def system_user_path(self):
        return self._system_user_path

    @property
    def is_existing_only(self):
        return self._existing_only

    @property
    def is_auto_port(self):
        return self._auto_port

    @property
    def retry_times(self):
        return self._retry_times

    @property
    def retry_interval(self):
        return self._retry_interval

    @property
    def is_headless(self):
        return self._is_headless

    def set_retry(self, times=None, interval=None):
        if times is not None:
            self._retry_times = times
        if interval is not None:
            self._retry_interval = interval
        return self

    def set_argument(self, arg, value=None):
        self.remove_argument(arg)
        if value is not False:
            if arg == '--headless':
                if value == 'false':
                    self._is_headless = False
                else:
                    if value is None:
                        value = 'new'
                    self._arguments.append(f'--headless={value}')
                    self._is_headless = True
            else:
                arg_str = arg if value is None else f'{arg}={value}'
                self._arguments.append(arg_str)
        elif arg == '--headless':
            self._is_headless = False
        return self

    def remove_argument(self, value):
        elements_to_delete = [arg for arg in self._arguments if arg == value or arg.startswith(f'{value}=')]
        if not elements_to_delete:
            return self

        if len(elements_to_delete) == 1:
            self._arguments.remove(elements_to_delete[0])
        else:
            self._arguments = [arg for arg in self._arguments if arg not in elements_to_delete]

        return self

    def add_extension(self, path):
        self._extensions.append(path)
        return self

    def remove_extensions(self):
        self._extensions = []
        return self

    def set_pref(self, arg, value):
        self._prefs[arg] = value
        return self

    def remove_pref(self, arg):
        self._prefs.pop(arg, None)
        return self

    def remove_pref_from_file(self, arg):
        self._prefs_to_del.append(arg)
        return self

    def set_flag(self, flag, value=None):
        if value is False:
            self._flags.pop(flag, None)
        else:
            self._flags[flag] = value
        return self

    def clear_flags_in_file(self):
        self.clear_file_flags = True
        return self

    def clear_flags(self):
        self._flags = {}
        return self

    def clear_arguments(self):
        self._arguments = []
        return self

    def clear_prefs(self):
        self._prefs = {}
        return self

    def set_timeouts(self, base=None, page_load=None, script=None):
        if base is not None:
            self._timeouts['base'] = base
        if page_load is not None:
            self._timeouts['page_load'] = page_load
        if script is not None:
            self._timeouts['script'] = script

        return self

    def set_user(self, user='Default'):
        self.set_argument('--profile-directory', user)
        self._user = user
        return self

    def headless(self, on_off=True):
        on_off = 'new' if on_off else on_off
        return self.set_argument('--headless', on_off)

    def no_imgs(self, on_off=True):
        on_off = None if on_off else False
        return self.set_argument('--blink-settings=imagesEnabled=false', on_off)

    def no_js(self, on_off=True):
        on_off = None if on_off else False
        return self.set_argument('--disable-javascript', on_off)

    def mute(self, on_off=True):
        on_off = None if on_off else False
        return self.set_argument('--mute-audio', on_off)

    def incognito(self, on_off=True):
        on_off = None if on_off else False
        self.set_argument('--incognito', on_off)
        return self.set_argument('--inprivate', on_off)  # edge

    def new_env(self, on_off=True):
        self._new_env = on_off
        return self

    def ignore_certificate_errors(self, on_off=True):
        on_off = None if on_off else False
        return self.set_argument('--ignore-certificate-errors', on_off)

    def set_user_agent(self, user_agent):
        return self.set_argument('--user-agent', user_agent)

    def set_proxy(self, proxy):
        if search(r'.*?:.*?@.*?\..*', proxy):
            print(_S._lang.UNSUPPORTED_USER_PROXY)
        if proxy.lower().startswith('socks'):
            print(_S._lang.UNSUPPORTED_SOCKS_PROXY)
        self._proxy = proxy
        return self.set_argument('--proxy-server', proxy)

    def set_load_mode(self, value):
        if value not in ('normal', 'eager', 'none'):
            raise ValueError(_S._lang.join(_S._lang.INCORRECT_VAL_, 'value',
                                           ALLOW_VAL="'normal', 'eager', 'none'", CURR_VAL=value))
        self._load_mode = value.lower()
        return self

    def set_paths(self, browser_path=None, local_port=None, address=None, download_path=None,
                  user_data_path=None, cache_path=None):
        """快捷的路径设置函数,即将废弃
        :param browser_path: 浏览器可执行文件路径
        :param local_port: 本地端口号
        :param address: 调试浏览器地址,例:127.0.0.1:9222
        :param download_path: 下载文件路径
        :param user_data_path: 用户数据路径
        :param cache_path: 缓存路径
        :return: 当前对象
        """
        if browser_path is not None:
            self.set_browser_path(browser_path)

        if local_port is not None:
            self.set_local_port(local_port)

        if address is not None:
            self.set_address(address)

        if download_path is not None:
            self.set_download_path(download_path)

        if user_data_path is not None:
            self.set_user_data_path(user_data_path)

        if cache_path is not None:
            self.set_cache_path(cache_path)

        return self

    def set_local_port(self, port):
        self._address = f'127.0.0.1:{port}'
        self._auto_port = False
        self.ws_address = ''
        return self

    def set_address(self, address):
        address = address.replace('localhost', '127.0.0.1')
        self.ws_address = ''
        if address.startswith('http'):
            address = address.lstrip('htps:/')
        elif address.startswith(('ws:', 'wss:')):
            self.ws_address = address
            address = urlparse(address).netloc
        self._address = address
        self._auto_port = False
        return self

    def set_browser_path(self, path):
        self._browser_path = str(path)
        return self

    def set_download_path(self, path):
        self._download_path = '.' if path is None else str(path)
        return self

    def set_tmp_path(self, path):
        self._tmp_path = str(path)
        return self

    def set_user_data_path(self, path):
        u = str(path)
        self.set_argument('--user-data-dir', u)
        self._user_data_path = u
        self._auto_port = False
        return self

    def set_cache_path(self, path):
        self.set_argument('--disk-cache-dir', str(path))
        return self

    def use_system_user_path(self, on_off=True):
        self._system_user_path = on_off
        return self

    def auto_port(self, on_off=True, scope=None):
        if on_off:
            self._auto_port = scope if scope else (9600, 59600)
        else:
            self._auto_port = False
        self._address = ''
        self.ws_address = ''
        return self

    def existing_only(self, on_off=True):
        self._existing_only = on_off
        return self

    def save(self, path=None):
        if path == 'default':
            path = (Path(__file__).parent / 'configs.ini').absolute()

        elif path is None:
            if self.ini_path:
                path = Path(self.ini_path).absolute()
            else:
                path = (Path(__file__).parent / 'configs.ini').absolute()

        else:
            path = Path(path).absolute()

        path = path / 'config.ini' if path.is_dir() else path

        if path.exists():
            om = OptionsManager(path)
        else:
            om = OptionsManager(self.ini_path or (Path(__file__).parent / 'configs.ini'))

        # 设置chromium_options
        attrs = ('address', 'browser_path', 'arguments', 'extensions', 'user', 'load_mode',
                 'auto_port', 'system_user_path', 'existing_only', 'flags', 'new_env')
        for i in attrs:
            om.set_item('chromium_options', i, self.__getattribute__(f'_{i}'))
        # 设置代理
        om.set_item('proxies', 'http', self._proxy or '')
        om.set_item('proxies', 'https', self._proxy or '')
        # 设置路径
        om.set_item('paths', 'download_path', self._download_path or '')
        om.set_item('paths', 'tmp_path', self._tmp_path or '')
        # 设置timeout
        om.set_item('timeouts', 'base', self._timeouts['base'])
        om.set_item('timeouts', 'page_load', self._timeouts['page_load'])
        om.set_item('timeouts', 'script', self._timeouts['script'])
        # 设置重试
        om.set_item('others', 'retry_times', self.retry_times)
        om.set_item('others', 'retry_interval', self.retry_interval)
        # 设置prefs
        om.set_item('chromium_options', 'prefs', self._prefs)

        path = str(path)
        om.save(path)

        return path

    def save_to_default(self):
        return self.save('default')


================================================
FILE: DrissionPage/_configs/chromium_options.pyi
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from pathlib import Path
from typing import Union, Any, Literal, Optional, Tuple


class ChromiumOptions(object):
    ini_path: Optional[str] = ...
    _user_data_path: Optional[str] = ...
    _download_path: str = ...
    _tmp_path: str = ...
    _arguments: list = ...
    _browser_path: str = ...
    _user: str = ...
    _load_mode: str = ...
    _timeouts: dict = ...
    _proxy: str = ...
    _address: str = ...
    _extensions: list = ...
    _prefs: dict = ...
    _flags: dict = ...
    _prefs_to_del: list = ...
    _new_env: bool = ...
    clear_file_flags: bool = ...
    _auto_port: Union[Tuple[int, int], False] = ...
    _system_user_path: bool = ...
    _existing_only: bool = ...
    _retry_times: int = ...
    _retry_interval: float = ...
    _is_headless: bool = ...
    _ua_set: bool = ...
    ws_address: Optional[str] = ...

    def __init__(self,
                 read_file: [bool, None] = True,
                 ini_path: Union[str, Path] = None):
        """
        :param read_file: 是否从默认ini文件中读取配置信息
        :param ini_path: ini文件路径,为None则读取默认ini文件
        """
        ...

    @property
    def download_path(self) -> str:
        """默认下载路径文件路径"""
        ...

    @property
    def browser_path(self) -> str:
        """浏览器启动文件路径"""
        ...

    @property
    def user_data_path(self) -> str:
        """返回用户数据文件夹路径"""
        ...

    @property
    def tmp_path(self) -> Optional[str]:
        """返回临时文件夹路径"""
        ...

    @property
    def user(self) -> str:
        """返回用户配置文件夹名称"""
        ...

    @property
    def load_mode(self) -> str:
        """返回页面加载策略,'normal', 'eager', 'none'"""
        ...

    @property
    def timeouts(self) -> dict:
        """返回timeouts设置"""
        ...

    @property
    def proxy(self) -> str:
        """返回代理设置"""
        ...

    @property
    def address(self) -> str:
        """返回浏览器地址,ip:port"""
        ...

    @property
    def arguments(self) -> list:
        """返回浏览器命令行设置列表"""
        ...

    @property
    def extensions(self) -> list:
        """以list形式返回要加载的插件路径"""
        ...

    @property
    def preferences(self) -> dict:
        """返回用户首选项配置"""
        ...

    @property
    def flags(self) -> dict:
        """返回实验项配置"""
        ...

    @property
    def system_user_path(self) -> bool:
        """返回是否使用系统安装的浏览器所使用的用户数据文件夹"""
        ...

    @property
    def is_existing_only(self) -> bool:
        """返回是否只接管现有浏览器方式"""
        ...

    @property
    def is_auto_port(self) -> Union[bool, Tuple[int, int]]:
        """返回是否使用自动端口和用户文件,如指定范围则返回范围tuple"""
        ...

    @property
    def retry_times(self) -> int:
        """返回连接失败时的重试次数"""
        ...

    @property
    def retry_interval(self) -> float:
        """返回连接失败时的重试间隔(秒)"""
        ...

    @property
    def is_headless(self) -> bool:
        """返回是否无头模式"""
        ...

    def set_retry(self, times: int = None, interval: float = None) -> ChromiumOptions:
        """设置连接失败时的重试操作
        :param times: 重试次数
        :param interval: 重试间隔
        :return: 当前对象
        """
        ...

    def set_argument(self, arg: str, value: Union[str, None, bool] = None) -> ChromiumOptions:
        """设置浏览器配置的argument属性
        :param arg: 属性名
        :param value: 属性值,有值的属性传入值,没有的传入None,如传入False,删除该项
        :return: 当前对象
        """
        ...

    def remove_argument(self, value: str) -> ChromiumOptions:
        """移除一个argument项
        :param value: 设置项名,有值的设置项传入设置名称即可
        :return: 当前对象
        """
        ...

    def add_extension(self, path: Union[str, Path]) -> ChromiumOptions:
        """添加插件
        :param path: 插件路径,可指向文件夹
        :return: 当前对象
        """
        ...

    def remove_extensions(self) -> ChromiumOptions:
        """移除所有插件
        :return: 当前对象
        """
        ...

    def set_pref(self, arg: str, value: Any) -> ChromiumOptions:
        """设置Preferences文件中的用户设置项
        :param arg: 设置项名称
        :param value: 设置项值
        :return: 当前对象
        """
        ...

    def remove_pref(self, arg: str) -> ChromiumOptions:
        """删除用户首选项设置,不能删除已设置到文件中的项
        :param arg: 设置项名称
        :return: 当前对象
        """
        ...

    def remove_pref_from_file(self, arg: str) -> ChromiumOptions:
        """删除用户配置文件中已设置的项
        :param arg: 设置项名称
        :return: 当前对象
        """
        ...

    def set_flag(self, flag: str, value: Union[int, str, bool] = None) -> ChromiumOptions:
        """设置实验项
        :param flag: 设置项名称
        :param value: 设置项的值,为False则删除该项
        :return: 当前对象
        """
        ...

    def clear_flags_in_file(self) -> ChromiumOptions:
        """删除浏览器配置文件中已设置的实验项"""
        ...

    def clear_flags(self) -> ChromiumOptions:
        """清空本对象已设置的flag参数"""
        ...

    def clear_arguments(self) -> ChromiumOptions:
        """清空本对象已设置的argument参数"""
        ...

    def clear_prefs(self) -> ChromiumOptions:
        """清空本对象已设置的pref参数"""
        ...

    def set_timeouts(self,
                     base: float = None,
                     page_load: float = None,
                     script: float = None) -> ChromiumOptions:
        """设置超时时间,单位为秒
        :param base: 默认超时时间
        :param page_load: 页面加载超时时间
        :param script: 脚本运行超时时间
        :return: 当前对象
        """
        ...

    def set_user(self, user: str = 'Default') -> ChromiumOptions:
        """设置使用哪个用户配置文件夹
        :param user: 用户文件夹名称
        :return: 当前对象
        """
        ...

    def headless(self, on_off: bool = True) -> ChromiumOptions:
        """设置是否隐藏浏览器界面
        :param on_off: 开或关
        :return: 当前对象
        """
        ...

    def no_imgs(self, on_off: bool = True) -> ChromiumOptions:
        """设置是否加载图片
        :param on_off: 开或关
        :return: 当前对象
        """
        ...

    def no_js(self, on_off: bool = True) -> ChromiumOptions:
        """设置是否禁用js
        :param on_off: 开或关
        :return: 当前对象
        """
        ...

    def mute(self, on_off: bool = True) -> ChromiumOptions:
        """设置是否静音
        :param on_off: 开或关
        :return: 当前对象
        """
        ...

    def incognito(self, on_off: bool = True) -> ChromiumOptions:
        """设置是否使用无痕模式启动
        :param on_off: 开或关
        :return: 当前对象
        """
        ...

    def new_env(self, on_off: bool = True) -> ChromiumOptions:
        """设置是否使用全新浏览器环境
        :param on_off: 开或关
        :return: 当前对象
        """
        ...

    def ignore_certificate_errors(self, on_off=True) -> ChromiumOptions:
        """设置是否忽略证书错误
        :param on_off: 开或关
        :return: 当前对象
        """
        ...

    def set_user_agent(self, user_agent: str) -> ChromiumOptions:
        """设置user agent
        :param user_agent: user agent文本
        :return: 当前对象
        """
        ...

    def set_proxy(self, proxy: str) -> ChromiumOptions:
        """设置代理
        :param proxy: 代理url和端口
        :return: 当前对象
        """
        ...

    def set_load_mode(self, value: Literal['normal', 'eager', 'none']) -> ChromiumOptions:
        """设置load_mode,可接收 'normal', 'eager', 'none'
        normal:默认情况下使用, 等待所有资源下载完成
        eager:DOM访问已准备就绪, 但其他资源 (如图像) 可能仍在加载中
        none:完全不阻塞
        :param value: 可接收 'normal', 'eager', 'none'
        :return: 当前对象
        """
        ...

    def set_local_port(self, port: Union[str, int]) -> ChromiumOptions:
        """设置本地启动端口,与set_address()和auto_port()互斥
        :param port: 端口号
        :return: 当前对象
        """
        ...

    def set_address(self, address: str) -> ChromiumOptions:
        """设置浏览器地址,格式'ip:port',与auto_port()和set_local_port()互斥
        :param address: 浏览器地址
        :return: 当前对象
        """
        ...

    def set_browser_path(self, path: Union[str, Path]) -> ChromiumOptions:
        """设置浏览器可执行文件路径
        :param path: 浏览器路径
        :return: 当前对象
        """
        ...

    def set_download_path(self, path: Union[str, Path]) -> ChromiumOptions:
        """设置下载文件保存路径
        :param path: 下载路径
        :return: 当前对象
        """
        ...

    def set_tmp_path(self, path: Union[str, Path]) -> ChromiumOptions:
        """设置临时文件文件保存路径
        :param path: 下载路径
        :return: 当前对象
        """
        ...

    def set_user_data_path(self, path: Union[str, Path]) -> ChromiumOptions:
        """设置用户文件夹路径
        :param path: 用户文件夹路径
        :return: 当前对象
        """
        ...

    def set_cache_path(self, path: Union[str, Path]) -> ChromiumOptions:
        """设置缓存路径
        :param path: 缓存路径
        :return: 当前对象
        """
        ...

    def use_system_user_path(self, on_off: bool = True) -> ChromiumOptions:
        """设置是否使用系统安装的浏览器默认用户文件夹
        :param on_off: 开或关
        :return: 当前对象
        """
        ...

    def auto_port(self,
                  on_off: bool = True,
                  scope: Tuple[int, int] = None) -> ChromiumOptions:
        """自动获取可用端口,与set_address()和set_local_port()互斥
        :param on_off: 是否开启自动获取端口号
        :param scope: 指定端口范围,不含最后的数字,为None则使用[9600-59600)
        :return: 当前对象
        """
        ...

    def existing_only(self, on_off: bool = True) -> ChromiumOptions:
        """设置只接管已有浏览器,不自动启动新的
        :param on_off: 是否开启自动获取端口号
        :return: 当前对象
        """
        ...

    def save(self, path: Union[str, Path] = None) -> str:
        """保存设置到文件
        :param path: ini文件的路径, None 保存到当前读取的配置文件,传入 'default' 保存到默认ini文件
        :return: 保存文件的绝对路径
        """
        ...

    def save_to_default(self) -> str:
        """保存当前配置到默认ini文件"""
        ...


================================================
FILE: DrissionPage/_configs/configs.ini
================================================
[paths]
download_path =
tmp_path =

[chromium_options]
address = 127.0.0.1:9222
browser_path = chrome
arguments = ['--no-default-browser-check', '--disable-suggestions-ui', '--no-first-run', '--disable-infobars', '--disable-popup-blocking', '--hide-crash-restore-bubble', '--disable-features=PrivacySandboxSettings4']
extensions = []
prefs = {'profile.default_content_settings.popups': 0, 'profile.default_content_setting_values': {'notifications': 2}}
flags = {}
load_mode = normal
user = Default
auto_port = False
system_user_path = False
existing_only = False
new_env = False

[session_options]
headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8', 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'connection': 'keep-alive', 'accept-charset': 'GB2312,utf-8;q=0.7,*;q=0.7'}

[timeouts]
base = 10
page_load = 30
script = 30

[proxies]
http =
https = 

[others]
retry_times = 3
retry_interval = 2


================================================
FILE: DrissionPage/_configs/options_manage.py
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from configparser import RawConfigParser, NoSectionError, NoOptionError
from pathlib import Path
from pprint import pprint

from .._functions.settings import Settings as _S


class OptionsManager(object):
    def __init__(self, path=None):
        if path is False:
            self.ini_path = None
        else:
            default_configs = Path(__file__).parent / 'configs.ini'
            if path is None:
                dp_configs = Path('dp_configs.ini')
                if dp_configs.exists():
                    self.ini_path = dp_configs
                else:
                    self.ini_path = default_configs
            elif path == 'default':
                self.ini_path = default_configs
            elif isinstance(path, Path):
                self.ini_path = path
            else:
                self.ini_path = Path(path)

        self._conf = RawConfigParser()
        if path is not False and self.ini_path.exists():
            self.file_exists = True
            self._conf.read(self.ini_path, encoding='utf-8')
        else:
            self.file_exists = False
            self._conf.add_section('paths')
            self._conf.add_section('chromium_options')
            self._conf.add_section('session_options')
            self._conf.add_section('timeouts')
            self._conf.add_section('proxies')
            self._conf.add_section('others')
            self.set_item('paths', 'download_path', '')
            self.set_item('paths', 'tmp_path', '')
            self.set_item('chromium_options', 'address', '127.0.0.1:9222')
            self.set_item('chromium_options', 'browser_path', 'chrome')
            self.set_item('chromium_options', 'arguments', "['--no-default-browser-check', '--disable-suggestions-ui', "
                                                           "'--no-first-run', '--disable-infobars', "
                                                           "'--disable-popup-blocking', '--hide-crash-restore-bubble', "
                                                           "'--disable-features=PrivacySandboxSettings4']")
            self.set_item('chromium_options', 'extensions', '[]')
            self.set_item('chromium_options', 'prefs', "{'profile.default_content_settings.popups': 0, "
                                                       "'profile.default_content_setting_values': "
                                                       "{'notifications': 2}}")
            self.set_item('chromium_options', 'flags', '{}')
            self.set_item('chromium_options', 'load_mode', 'normal')
            self.set_item('chromium_options', 'user', 'Default')
            self.set_item('chromium_options', 'auto_port', 'False')
            self.set_item('chromium_options', 'system_user_path', 'False')
            self.set_item('chromium_options', 'existing_only', 'False')
            self.set_item('chromium_options', 'new_env', 'False')
            self.set_item('session_options', 'headers', "{'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X "
                                                        "10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10."
                                                        "1.2 Safari/603.3.8', 'accept': 'text/html,application/xhtml"
                                                        "+xml,application/xml;q=0.9,*/*;q=0.8', 'connection': "
                                                        "'keep-alive', 'accept-charset': 'GB2312,utf-8;q=0.7,*;q=0.7'}")
            self.set_item('timeouts', 'base', '10')
            self.set_item('timeouts', 'page_load', '30')
            self.set_item('timeouts', 'script', '30')
            self.set_item('proxies', 'http', '')
            self.set_item('proxies', 'https', '')
            self.set_item('others', 'retry_times', '3')
            self.set_item('others', 'retry_interval', '2')

    def __getattr__(self, item):
        return self.get_option(item)

    def get_value(self, section, item):
        try:
            return eval(self._conf.get(section, item))
        except (SyntaxError, NameError):
            return self._conf.get(section, item)
        except NoSectionError and NoOptionError:
            return None

    def get_option(self, section):
        items = self._conf.items(section)
        option = dict()

        for j in items:
            try:
                option[j[0]] = eval(self._conf.get(section, j[0]))
            except Exception:
                option[j[0]] = self._conf.get(section, j[0])

        return option

    def set_item(self, section, item, value):
        self._conf.set(section, item, str(value))
        self.__setattr__(f'_{section}', None)
        return self

    def remove_item(self, section, item):
        self._conf.remove_option(section, item)
        return self

    def save(self, path=None):
        default_path = (Path(__file__).parent / 'configs.ini').absolute()
        if path == 'default':
            path = default_path
        elif path is None:
            if self.ini_path is None:
                raise RuntimeError(_S._lang.join(_S._lang.INI_NOT_SET))
            path = self.ini_path.absolute()
        else:
            path = Path(path).absolute()

        path = path / 'config.ini' if path.is_dir() else path
        path.parent.mkdir(exist_ok=True, parents=True)

        path = str(path)
        self._conf.write(open(path, 'w', encoding='utf-8'))

        print(f'{_S._lang.OPTIONS_HAVE_SAVED}: {path}')
        if path == str(default_path):
            print(_S._lang.AUTO_LOAD_TIP)

        self.file_exists = True
        return path

    def save_to_default(self):
        return self.save('default')

    def show(self):
        for i in self._conf.sections():
            print(f'[{i}]')
            pprint(self.get_option(i))
            print()


================================================
FILE: DrissionPage/_configs/options_manage.pyi
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from configparser import RawConfigParser
from pathlib import Path
from typing import Any, Optional, Union


class OptionsManager(object):
    """管理配置文件内容的类"""
    ini_path: Optional[Path] = ...
    file_exists: bool = ...
    _conf: RawConfigParser = ...

    def __init__(self, path: Union[Path, str] = None):
        """初始化,读取配置文件,如没有设置临时文件夹,则设置并新建
        :param path: ini文件的路径,为None则找项目文件夹下的,找不到则读取模块文件夹下的
        """
        ...

    def __getattr__(self, item) -> dict:
        """以dict形似返回获取大项信息
        :param item: 项名
        :return: None
        """
        ...

    def get_value(self, section: str, item: str) -> Any:
        """获取配置的值
        :param section: 段名
        :param item: 项名
        :return: 项值
        """
        ...

    def get_option(self, section: str) -> dict:
        """把section内容以字典方式返回
        :param section: 段名
        :return: 段内容生成的字典
        """
        ...

    def set_item(self, section: str, item: str, value: Any) -> None:
        """设置配置值
        :param section: 段名
        :param item: 项名
        :param value: 项值
        :return: None
        """
        ...

    def remove_item(self, section: str, item: str) -> None:
        """删除配置值
        :param section: 段名
        :param item: 项名
        :return: None
        """
        ...

    def save(self, path: str = None) -> str:
        """保存配置文件
        :param path: ini文件的路径,传入 'default' 保存到默认ini文件
        :return: 保存路径
        """
        ...

    def save_to_default(self) -> str:
        """保存当前配置到默认ini文件"""
        ...

    def show(self) -> None:
        """打印所有设置信息"""
        ...


================================================
FILE: DrissionPage/_configs/session_options.py
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from copy import copy
from pathlib import Path

from requests import Session
from requests.structures import CaseInsensitiveDict

from .options_manage import OptionsManager
from .._functions.cookies import cookies_to_tuple, set_session_cookies
from .._functions.settings import Settings as _S
from .._functions.web import format_headers


class SessionOptions(object):

    def __init__(self, read_file=True, ini_path=None):
        self.ini_path = None
        self._download_path = '.'
        self._timeout = 10
        self._del_set = set()  # 记录要从ini文件删除的参数

        if read_file is False:
            ini_path = False
            self.ini_path = None
        elif ini_path:
            ini_path = Path(ini_path).absolute()
            if not ini_path.exists():
                raise FileNotFoundError(_S._lang.join(_S._lang.INI_NOT_FOUND, PATH=ini_path))
            self.ini_path = str(ini_path)
        else:
            self.ini_path = str(Path(__file__).parent / 'configs.ini')
        om = OptionsManager(ini_path)

        self._headers = None
        self._cookies = None
        self._auth = None
        self._proxies = None
        self._hooks = None
        self._params = None
        self._verify = None
        self._cert = None
        self._adapters = None
        self._stream = None
        self._trust_env = None
        self._max_redirects = None

        options = om.session_options
        if options.get('headers', None) is not None:
            self.set_headers(options['headers'])

        if options.get('cookies', None) is not None:
            self.set_cookies(options['cookies'])

        if options.get('auth', None) is not None:
            self._auth = options['auth']

        if options.get('params', None) is not None:
            self._params = options['params']

        if options.get('verify', None) is not None:
            self._verify = options['verify']

        if options.get('cert', None) is not None:
            self._cert = options['cert']

        if options.get('stream', None) is not None:
            self._stream = options['stream']

        if options.get('trust_env', None) is not None:
            self._trust_env = options['trust_env']

        if options.get('max_redirects', None) is not None:
            self._max_redirects = options['max_redirects']

        self.set_proxies(om.proxies.get('http', None), om.proxies.get('https', None))
        self._timeout = om.timeouts.get('base', 10)
        self._download_path = om.paths.get('download_path', '.') or '.'

        others = om.others
        self._retry_times = others.get('retry_times', 3)
        self._retry_interval = others.get('retry_interval', 2)

    def __repr__(self):
        return f'<SessionOptions at {id(self)}>'

    # ===========须独立处理的项开始============
    @property
    def download_path(self):
        return self._download_path

    def set_download_path(self, path):
        self._download_path = '.' if path is None else str(path)
        return self

    @property
    def timeout(self):
        return self._timeout

    def set_timeout(self, second):
        self._timeout = second
        return self

    @property
    def proxies(self):
        if self._proxies is None:
            self._proxies = {}
        return self._proxies

    def set_proxies(self, http=None, https=None):
        self._sets('proxies', {'http': http, 'https': https})
        return self

    @property
    def retry_times(self):
        return self._retry_times

    @property
    def retry_interval(self):
        return self._retry_interval

    def set_retry(self, times=None, interval=None):
        if times is not None:
            self._retry_times = times
        if interval is not None:
            self._retry_interval = interval
        return self

    # ===========须独立处理的项结束============

    @property
    def headers(self):
        if self._headers is None:
            self._headers = {}
        return self._headers

    def set_headers(self, headers):
        if headers is None:
            self._headers = None
            self._del_set.add('headers')
        else:
            headers = format_headers(headers)
            self._headers = {key.lower(): headers[key] for key in headers}
        return self

    def set_a_header(self, name, value):
        if self._headers is None:
            self._headers = {}

        self._headers[name.lower()] = value
        return self

    def remove_a_header(self, name):
        if self._headers is None:
            return self

        self._headers.pop(name.lower(), None)

        return self

    def clear_headers(self):
        self._headers = None
        self._del_set.add('headers')

    @property
    def cookies(self):
        if self._cookies is None:
            self._cookies = []
        return self._cookies

    def set_cookies(self, cookies):
        cookies = cookies if cookies is None else list(cookies_to_tuple(cookies))
        self._sets('cookies', cookies)
        return self

    @property
    def auth(self):
        return self._auth

    def set_auth(self, auth):
        self._sets('auth', auth)
        return self

    @property
    def hooks(self):
        if self._hooks is None:
            self._hooks = {}
        return self._hooks

    def set_hooks(self, hooks):
        self._hooks = hooks
        return self

    @property
    def params(self):
        if self._params is None:
            self._params = {}
        return self._params

    def set_params(self, params):
        self._sets('params', params)
        return self

    @property
    def verify(self):
        return self._verify

    def set_verify(self, on_off):
        self._sets('verify', on_off)
        return self

    @property
    def cert(self):
        return self._cert

    def set_cert(self, cert):
        self._sets('cert', cert)
        return self

    @property
    def adapters(self):
        if self._adapters is None:
            self._adapters = []
        return self._adapters

    def add_adapter(self, url, adapter):
        self._adapters.append((url, adapter))
        return self

    @property
    def stream(self):
        return self._stream

    def set_stream(self, on_off):
        self._sets('stream', on_off)
        return self

    @property
    def trust_env(self):
        return self._trust_env

    def set_trust_env(self, on_off):
        self._sets('trust_env', on_off)
        return self

    @property
    def max_redirects(self):
        return self._max_redirects

    def set_max_redirects(self, times):
        self._sets('max_redirects', times)
        return self

    def _sets(self, arg, val):
        if val is None:
            self.__setattr__(f'_{arg}', None)
            self._del_set.add(arg)
        else:
            self.__setattr__(f'_{arg}', val)
            if arg in self._del_set:
                self._del_set.remove(arg)

    def save(self, path=None):
        if path == 'default':
            path = (Path(__file__).parent / 'configs.ini').absolute()

        elif path is None:
            if self.ini_path:
                path = Path(self.ini_path).absolute()
            else:
                path = (Path(__file__).parent / 'configs.ini').absolute()

        else:
            path = Path(path).absolute()

        path = path / 'config.ini' if path.is_dir() else path

        if path.exists():
            om = OptionsManager(path)
        else:
            om = OptionsManager(self.ini_path or (Path(__file__).parent / 'configs.ini'))

        options = session_options_to_dict(self)

        for i in options:
            if i not in ('download_path', 'timeout', 'proxies'):
                om.set_item('session_options', i, options[i])

        om.set_item('paths', 'download_path', self.download_path or '')
        om.set_item('timeouts', 'base', self.timeout)
        om.set_item('proxies', 'http', self.proxies.get('http', ''))
        om.set_item('proxies', 'https', self.proxies.get('https', ''))
        om.set_item('others', 'retry_times', self.retry_times)
        om.set_item('others', 'retry_interval', self.retry_interval)

        for i in self._del_set:
            if i == 'download_path':
                om.set_item('paths', 'download_path', '')
            elif i == 'proxies':
                om.set_item('proxies', 'http', '')
                om.set_item('proxies', 'https', '')
            else:
                om.remove_item('session_options', i)

        path = str(path)
        om.save(path)

        return path

    def save_to_default(self):
        return self.save('default')

    def as_dict(self):
        return session_options_to_dict(self)

    def make_session(self):
        s = Session()
        h = CaseInsensitiveDict(self.headers) if self.headers else CaseInsensitiveDict()

        if self.cookies:
            set_session_cookies(s, self.cookies)
        if self.adapters:
            for url, adapter in self.adapters:
                s.mount(url, adapter)

        for i in ['auth', 'proxies', 'hooks', 'params', 'verify', 'cert', 'stream', 'trust_env', 'max_redirects']:
            attr = self.__getattribute__(i)
            if attr:
                s.__setattr__(i, attr)

        return s, h

    def from_session(self, session, headers=None):
        self._headers = CaseInsensitiveDict(copy(session.headers).update(headers)) if headers else session.headers
        self._cookies = session.cookies
        self._auth = session.auth
        self._proxies = session.proxies
        self._hooks = session.hooks
        self._params = session.params
        self._verify = session.verify
        self._cert = session.cert
        self._stream = session.stream
        self._trust_env = session.trust_env
        self._max_redirects = session.max_redirects
        if session.adapters:
            self._adapters = [(k, i) for k, i in session.adapters.items()]
        return self


def session_options_to_dict(options):
    if options in (False, None):
        return SessionOptions(read_file=False).as_dict()

    if isinstance(options, dict):
        return options

    re_dict = dict()
    attrs = ['headers', 'cookies', 'proxies', 'params', 'verify', 'stream', 'trust_env', 'cert',
             'max_redirects', 'timeout', 'download_path']

    for attr in attrs:
        val = options.__getattribute__(f'_{attr}')
        if val is not None:
            re_dict[attr] = val

    return re_dict


================================================
FILE: DrissionPage/_configs/session_options.pyi
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from http.cookiejar import CookieJar, Cookie
from pathlib import Path
from typing import Any, Union, Tuple, Optional

from requests import Session
from requests.adapters import HTTPAdapter
from requests.auth import HTTPBasicAuth
from requests.cookies import RequestsCookieJar
from requests.structures import CaseInsensitiveDict


class SessionOptions(object):
    """requests的Session对象配置类"""

    ini_path: Optional[str] = ...
    _download_path: str = ...
    _headers: Union[dict, CaseInsensitiveDict, None] = ...
    _cookies: Union[list, RequestsCookieJar, None] = ...
    _auth: Optional[tuple] = ...
    _proxies: Optional[dict] = ...
    _hooks: Optional[dict] = ...
    _params: Union[dict, None] = ...
    _verify: Optional[bool] = ...
    _cert: Union[str, tuple, None] = ...
    _adapters: Optional[list] = ...
    _stream: Optional[bool] = ...
    _trust_env: Optional[bool] = ...
    _max_redirects: Optional[int] = ...
    _timeout: float = ...
    _del_set: set = ...
    _retry_times: int = ...
    _retry_interval: float = ...

    def __init__(self,
                 read_file: [bool, None] = True,
                 ini_path: Union[str, Path] = None):
        """
        :param read_file: 是否从文件读取配置
        :param ini_path: ini文件路径
        """
        ...

    @property
    def download_path(self) -> str:
        """返回默认下载路径属性信息"""
        ...

    def set_download_path(self, path: Union[str, Path]) -> SessionOptions:
        """设置默认下载路径
        :param path: 下载路径
        :return: 返回当前对象
        """
        ...

    @property
    def timeout(self) -> float:
        """返回timeout属性信息"""
        ...

    def set_timeout(self, second: float) -> SessionOptions:
        """设置超时信息
        :param second: 秒数
        :return: 返回当前对象
        """
        ...

    @property
    def proxies(self) -> dict:
        """返回proxies设置信息"""
        ...

    def set_proxies(self, http: Union[str, None], https: Union[str, None] = None) -> SessionOptions:
        """设置proxies参数
        :param http: http代理地址
        :param https: https代理地址
        :return: 返回当前对象
        """
        ...

    @property
    def retry_times(self) -> int:
        """返回连接失败时的重试次数"""
        ...

    @property
    def retry_interval(self) -> float:
        """返回连接失败时的重试间隔(秒)"""
        ...

    def set_retry(self, times: int = None, interval: float = None) -> SessionOptions:
        """设置连接失败时的重试操作
        :param times: 重试次数
        :param interval: 重试间隔
        :return: 当前对象
        """
        ...

    @property
    def headers(self) -> dict:
        """返回headers设置信息"""
        ...

    def set_headers(self, headers: Union[dict, str, None]) -> SessionOptions:
        """设置headers参数
        :param headers: 参数值,传入None可在ini文件标记删除
        :return: 返回当前对象
        """
        ...

    def set_a_header(self, name: str, value: str) -> SessionOptions:
        """设置headers中一个项
        :param name: 设置名称
        :param value: 设置值
        :return: 返回当前对象
        """
        ...

    def remove_a_header(self, name: str) -> SessionOptions:
        """从headers中删除一个设置
        :param name: 要删除的设置
        :return: 返回当前对象
        """
        ...

    def clear_headers(self) -> SessionOptions:
        """清空已设置的header参数"""
        ...

    @property
    def cookies(self) -> list:
        """以list形式返回cookies"""
        ...

    def set_cookies(self, cookies: Union[Cookie, CookieJar, list, tuple, str, dict, None]) -> SessionOptions:
        """设置一个或多个cookies信息
        :param cookies: cookies,可为Cookie, CookieJar, list, tuple, str, dict,传入None可在ini文件标记删除
        :return: 返回当前对象
        """
        ...

    @property
    def auth(self) -> Union[Tuple[str, str], HTTPBasicAuth]:
        """返回认证设置信息"""
        ...

    def set_auth(self, auth: Union[Tuple[str, str], HTTPBasicAuth, None]) -> SessionOptions:
        """设置认证元组或对象
        :param auth: 认证元组或对象
        :return: 返回当前对象
        """
        ...

    @property
    def hooks(self) -> dict:
        """返回回调方法"""
        ...

    def set_hooks(self, hooks: Union[dict, None]) -> SessionOptions:
        """设置回调方法
        :param hooks: 回调方法
        :return: 返回当前对象
        """
        ...

    @property
    def params(self) -> dict:
        """返回连接参数设置信息"""
        ...

    def set_params(self, params: Union[dict, None]) -> SessionOptions:
        """设置查询参数字典
        :param params: 查询参数字典
        :return: 返回当前对象
        """
        ...

    @property
    def verify(self) -> bool:
        """返回是否验证SSL证书设置"""
        ...

    def set_verify(self, on_off: Union[bool, None]) -> SessionOptions:
        """设置是否验证SSL证书
        :param on_off: 是否验证 SSL 证书
        :return: 返回当前对象
        """
        ...

    @property
    def cert(self) -> Union[str, tuple]:
        """返回SSL证书设置信息"""
        ...

    def set_cert(self, cert: Union[str, Tuple[str, str], None]) -> SessionOptions:
        """SSL客户端证书文件的路径(.pem格式),或('cert', 'key')元组
        :param cert: 证书路径或元组
        :return: 返回当前对象
        """
        ...

    @property
    def adapters(self) -> list:
        """返回适配器设置信息"""
        ...

    def add_adapter(self, url: str, adapter: HTTPAdapter) -> SessionOptions:
        """添加适配器
        :param url: 适配器对应url
        :param adapter: 适配器对象
        :return: 返回当前对象
        """
        ...

    @property
    def stream(self) -> bool:
        """返回是否使用流式响应内容设置信息"""
        ...

    def set_stream(self, on_off: Union[bool, None]) -> SessionOptions:
        """设置是否使用流式响应内容
        :param on_off: 是否使用流式响应内容
        :return: 返回当前对象
        """
        ...

    @property
    def trust_env(self) -> bool:
        """返回是否信任环境设置信息"""
        ...

    def set_trust_env(self, on_off: Union[bool, None]) -> SessionOptions:
        """设置是否信任环境
        :param on_off: 是否信任环境
        :return: 返回当前对象
        """
        ...

    @property
    def max_redirects(self) -> int:
        """返回最大重定向次数"""
        ...

    def set_max_redirects(self, times: Union[int, None]) -> SessionOptions:
        """设置最大重定向次数
        :param times: 最大重定向次数
        :return: 返回当前对象
        """
        ...

    def _sets(self, arg: str, val: Any) -> None:
        """给属性赋值或标记删除
        :param arg: 属性名称
        :param val: 参数值
        :return: None
        """
        ...

    def save(self, path: str = None) -> str:
        """保存设置到文件
        :param path: ini文件的路径,传入 'default' 保存到默认ini文件
        :return: 保存文件的绝对路径
        """
        ...

    def save_to_default(self) -> str:
        """保存当前配置到默认ini文件"""
        ...

    def as_dict(self) -> dict:
        """以字典形式返回本对象"""
        ...

    def make_session(self) -> Tuple[Session, Optional[CaseInsensitiveDict]]:
        """根据内在的配置生成Session对象,headers从对象中分离"""
        ...

    def from_session(self, session: Session, headers: CaseInsensitiveDict = None) -> SessionOptions:
        """从Session对象中读取配置
        :param session: Session对象
        :param headers: headers
        :return: 当前对象
        """
        ...


def session_options_to_dict(options: Union[dict, SessionOptions, None]) -> Union[dict, None]:
    """把session配置对象转换为字典
    :param options: session配置对象或字典
    :return: 配置字典
    """
    ...


================================================
FILE: DrissionPage/_elements/chromium_element.py
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from json import loads
from os.path import basename
from pathlib import Path
from platform import system
from re import search
from time import perf_counter, sleep

from DataRecorder.tools import get_usable_path, make_valid_name

from .none_element import NoneElement
from .session_element import make_session_ele
from .._base.base import DrissionElement, BaseElement
from .._functions.elements import ChromiumElementsList, SessionElementsList
from .._functions.keys import input_text_or_keys, Keys
from .._functions.locator import get_loc, locator_to_tuple
from .._functions.settings import Settings as _S
from .._functions.web import make_absolute_link, get_ele_txt, format_html, is_js_func, get_blob
from .._units.clicker import Clicker
from .._units.rect import ElementRect
from .._units.scroller import ElementScroller
from .._units.selector import SelectElement
from .._units.setter import ChromiumElementSetter
from .._units.states import ElementStates, ShadowRootStates
from .._units.waiter import ElementWaiter
from ..errors import (ContextLostError, ElementLostError, JavaScriptError, CDPError, NoResourceError,
                      AlertExistsError, NoRectError, LocatorError)

__FRAME_ELEMENT__ = ('iframe', 'frame')


class ChromiumElement(DrissionElement):

    def __init__(self, owner, node_id=None, obj_id=None, backend_id=None):
        super().__init__(owner)
        self.tab = self.owner._tab
        self._select = None
        self._scroll = None
        self._rect = None
        self._set = None
        self._states = None
        self._pseudo = None
        self._clicker = None
        self._tag = None
        self._wait = None
        self._type = 'ChromiumElement'
        self._doc_id = None

        if node_id and obj_id and backend_id:
            self._node_id = node_id
            self._obj_id = obj_id
            self._backend_id = backend_id
        elif node_id:
            self._node_id = node_id
            self._obj_id = self._get_obj_id(node_id)
            self._backend_id = self._get_backend_id(self._node_id)
        elif obj_id:
            self._node_id = self._get_node_id(obj_id)
            self._obj_id = obj_id
            self._backend_id = self._get_backend_id(self._node_id)
        elif backend_id:
            self._obj_id = self._get_obj_id(backend_id=backend_id)
            self._node_id = self._get_node_id(obj_id=self._obj_id)
            self._backend_id = backend_id
        else:
            raise ElementLostError

    def __call__(self, locator, index=1, timeout=None):
        return self.ele(locator, index=index, timeout=timeout)

    def __repr__(self):
        attrs = [f"{k}='{v}'" for k, v in self.attrs.items()]
        return f'<ChromiumElement {self.tag} {" ".join(attrs)}>'

    def __eq__(self, other):
        return self._backend_id == getattr(other, '_backend_id', None)

    @property
    def tag(self):
        if self._tag is None:
            self._tag = self.owner._run_cdp('DOM.describeNode',
                                            backendNodeId=self._backend_id)['node']['localName'].lower()
        return self._tag

    @property
    def html(self):
        return self.owner._run_cdp('DOM.getOuterHTML', backendNodeId=self._backend_id)['outerHTML']

    @property
    def inner_html(self):
        return self._run_js('return this.innerHTML;')

    @property
    def attrs(self):
        try:
            attrs = self.owner._run_cdp('DOM.getAttributes', nodeId=self._node_id)['attributes']
            return {attrs[i]: attrs[i + 1] for i in range(0, len(attrs), 2)}
        except ElementLostError:
            self._refresh_id()
            attrs = self.owner._run_cdp('DOM.getAttributes', nodeId=self._node_id)['attributes']
            return {attrs[i]: attrs[i + 1] for i in range(0, len(attrs), 2)}
        except CDPError:  # 文档根元素不能调用此方法
            return {}

    @property
    def text(self):
        return get_ele_txt(make_session_ele(self.html))

    @property
    def raw_text(self):
        return self.property('innerText')

    # -----------------d模式独有属性-------------------
    @property
    def set(self):
        if self._set is None:
            self._set = ChromiumElementSetter(self)
        return self._set

    @property
    def states(self):
        if self._states is None:
            self._states = ElementStates(self)
        return self._states

    @property
    def pseudo(self):
        if self._pseudo is None:
            self._pseudo = Pseudo(self)
        return self._pseudo

    @property
    def rect(self):
        if self._rect is None:
            self._rect = ElementRect(self)
        return self._rect

    @property
    def sr(self):
        end_time = perf_counter() + self.timeout
        while perf_counter() < end_time:
            info = self.owner._run_cdp('DOM.describeNode', backendNodeId=self._backend_id)['node']
            if info.get('shadowRoots', None):
                return ShadowRoot(self, backend_id=info['shadowRoots'][0]['backendNodeId'])
        return None

    @property
    def shadow_root(self):
        return self.sr

    @property
    def scroll(self):
        if self._scroll is None:
            self._scroll = ElementScroller(self)
        return self._scroll

    @property
    def click(self):
        if self._clicker is None:
            self._clicker = Clicker(self)
        return self._clicker

    @property
    def wait(self):
        if self._wait is None:
            self._wait = ElementWaiter(self)
        return self._wait

    @property
    def select(self):
        if self._select is None:
            if self.tag != 'select':
                self._select = False
            else:
                self._select = SelectElement(self)
        return self._select

    @property
    def value(self):
        return self.property('value')

    def check(self, uncheck=False, by_js=False):
        is_checked = self.states.is_checked
        if by_js:
            js = None
            if is_checked and uncheck:
                js = 'this.checked=false'
            elif not is_checked and not uncheck:
                js = 'this.checked=true'
            if js:
                self._run_js(js)
                self._run_js('this.dispatchEvent(new Event("change", {bubbles: true}));')

        else:
            if (is_checked and uncheck) or (not is_checked and not uncheck):
                self.click()

        return self

    def parent(self, level_or_loc=1, index=1, timeout=0):
        return super().parent(level_or_loc, index, timeout=timeout)

    def child(self, locator='', index=1, timeout=None, ele_only=True):
        return super().child(locator, index, timeout, ele_only=ele_only)

    def prev(self, locator='', index=1, timeout=None, ele_only=True):
        return super().prev(locator, index, timeout, ele_only=ele_only)

    def next(self, locator='', index=1, timeout=None, ele_only=True):
        return super().next(locator, index, timeout, ele_only=ele_only)

    def before(self, locator='', index=1, timeout=None, ele_only=True):
        return super().before(locator, index, timeout, ele_only=ele_only)

    def after(self, locator='', index=1, timeout=None, ele_only=True):
        return super().after(locator, index, timeout, ele_only=ele_only)

    def children(self, locator='', timeout=None, ele_only=True):
        return ChromiumElementsList(self.owner, super().children(locator, timeout, ele_only=ele_only))

    def prevs(self, locator='', timeout=None, ele_only=True):
        return ChromiumElementsList(self.owner, super().prevs(locator, timeout, ele_only=ele_only))

    def nexts(self, locator='', timeout=None, ele_only=True):
        return ChromiumElementsList(self.owner, super().nexts(locator, timeout, ele_only=ele_only))

    def befores(self, locator='', timeout=None, ele_only=True):
        return ChromiumElementsList(self.owner, super().befores(locator, timeout, ele_only=ele_only))

    def afters(self, locator='', timeout=None, ele_only=True):
        return ChromiumElementsList(self.owner, super().afters(locator, timeout, ele_only=ele_only))

    def over(self, timeout=None):
        if timeout is None:
            timeout = self.timeout
        bid = self.states.is_covered
        end_time = perf_counter() + timeout
        while not bid and perf_counter() < end_time:
            bid = self.states.is_covered
        return (ChromiumElement(owner=self.owner, backend_id=bid)
                if bid else NoneElement(page=self.owner, method='over()', args={'timeout': timeout}))

    def offset(self, locator=None, x=None, y=None, timeout=None):
        if locator and not (isinstance(locator, str) and not locator.startswith(
                ('x:', 'xpath:', 'x=', 'xpath=', 'c:', 'css:', 'c=', 'css='))):
            raise LocatorError(ALLOW_TYPE=_S._lang.STR_ONLY, CURR_VAL=locator)

        if x == y is None:
            x, y = self.rect.midpoint
            x = int(x)
            y = int(y)
        else:
            nx, ny = self.rect.location
            nx += x if x else 0
            ny += y if y else 0
            x = int(nx)
            y = int(ny)
        loc_data = locator_to_tuple(locator) if locator else None
        if timeout is None:
            timeout = self.timeout
        end_time = perf_counter() + timeout
        try:
            ele = ChromiumElement(owner=self.owner,
                                  backend_id=self.owner._run_cdp('DOM.getNodeForLocation', x=x, y=y,
                                                                 includeUserAgentShadowDOM=True,
                                                                 ignorePointerEventsNone=False)['backendNodeId'])
        except CDPError:
            ele = False
        if ele and (loc_data is None or _check_ele(ele, loc_data)):
            return ele

        while perf_counter() < end_time:
            try:
                ele = ChromiumElement(owner=self.owner,
                                      backend_id=self.owner._run_cdp('DOM.getNodeForLocation', x=x, y=y,
                                                                     includeUserAgentShadowDOM=True,
                                                                     ignorePointerEventsNone=False)['backendNodeId'])
            except CDPError:
                ele = False

            if ele and (loc_data is None or _check_ele(ele, loc_data)):
                return ele
            sleep(.01)

        return NoneElement(page=self.owner, method='offset()',
                           args={'locator': locator, 'offset_x': x, 'offset_y': y, 'timeout': timeout})

    def east(self, loc_or_pixel=None, index=1):
        return self._get_relative_eles(mode='east', locator=loc_or_pixel, index=index)

    def south(self, loc_or_pixel=None, index=1):
        return self._get_relative_eles(mode='south', locator=loc_or_pixel, index=index)

    def west(self, loc_or_pixel=None, index=1):
        return self._get_relative_eles(mode='west', locator=loc_or_pixel, index=index)

    def north(self, loc_or_pixel=None, index=1):
        return self._get_relative_eles(mode='north', locator=loc_or_pixel, index=index)

    def _get_relative_eles(self, mode='north', locator=None, index=1):
        if locator and not (isinstance(locator, str) and not locator.startswith(
                ('x:', 'xpath:', 'x=', 'xpath=', 'c:', 'css:', 'c=', 'css=')) or isinstance(locator, int)):
            raise LocatorError(ALLOW_TYPE=_S._lang.STR_ONLY, CURR_VAL=locator)
        rect = self.states.has_rect
        if not rect:
            raise NoRectError

        if mode == 'east':
            cdp_data = {'x': int(rect[1][0]), 'y': int(self.rect.midpoint[1]),
                        'includeUserAgentShadowDOM': True, 'ignorePointerEventsNone': False}
            variable = 'x'
            minus = False
        elif mode == 'south':
            cdp_data = {'x': int(self.rect.midpoint[0]), 'y': int(rect[2][1]),
                        'includeUserAgentShadowDOM': True, 'ignorePointerEventsNone': False}
            variable = 'y'
            minus = False
        elif mode == 'west':
            cdp_data = {'x': int(rect[0][0]), 'y': int(self.rect.midpoint[1]),
                        'includeUserAgentShadowDOM': True, 'ignorePointerEventsNone': False}
            variable = 'x'
            minus = True
        else:  # north
            cdp_data = {'x': int(self.rect.midpoint[0]), 'y': int(rect[0][1]),
                        'includeUserAgentShadowDOM': True, 'ignorePointerEventsNone': False}
            variable = 'y'
            minus = True

        if isinstance(locator, int):
            if minus:
                cdp_data[variable] -= locator
            else:
                cdp_data[variable] += locator
            try:
                return ChromiumElement(owner=self.owner,
                                       backend_id=self.owner._run_cdp('DOM.getNodeForLocation',
                                                                      **cdp_data)['backendNodeId'])
            except CDPError:
                return NoneElement(page=self.owner, method=f'{mode}()', args={'locator': locator})

        num = 0
        value = -8 if minus else 8
        size = self.owner.rect.size
        max_len = size[0] if mode == 'east' else size[1]
        loc_data = locator_to_tuple(locator) if locator else None
        curr_ele = None
        while 0 < cdp_data[variable] < max_len:
            cdp_data[variable] += value
            try:
                bid = self.owner._run_cdp('DOM.getNodeForLocation', **cdp_data)['backendNodeId']
                if bid == curr_ele:
                    continue
                else:
                    curr_ele = bid
                ele = ChromiumElement(self.owner, backend_id=bid)

                if loc_data is None or _check_ele(ele, loc_data):
                    num += 1
                    if num == index:
                        return ele
            except:
                pass

        return NoneElement(page=self.owner, method=f'{mode}()', args={'locator': locator})

    def attr(self, name):
        attrs = self.attrs
        if name == 'href':
            link = attrs.get('href')
            if not link or link.lower().startswith(('javascript:', 'mailto:')):
                return link
            else:
                return make_absolute_link(link, self.property('baseURI'))

        elif name == 'src':
            return make_absolute_link(attrs.get('src'), self.property('baseURI'))

        elif name == 'text':
            return self.text

        elif name == 'innerText':
            return self.raw_text

        elif name in ('html', 'outerHTML'):
            return self.html

        elif name == 'innerHTML':
            return self.inner_html

        else:
            return attrs.get(name, None)

    def remove_attr(self, name):
        self._run_js(f'this.removeAttribute("{name}");')
        return self

    def property(self, name):
        try:
            value = self._run_js(f'return this.{name};')
            return format_html(value) if isinstance(value, str) else value
        except:
            return None

    def run_js(self, script, *args, as_expr=False, timeout=None):
        return self._run_js(script, *args, as_expr=as_expr, timeout=timeout)

    def _run_js(self, script, *args, as_expr=False, timeout=None):
        return run_js(self, script, as_expr, self.owner.timeouts.script if timeout is None else timeout, args)

    def run_async_js(self, script, *args, as_expr=False):
        run_js(self, script, as_expr, 0, args)

    def ele(self, locator, index=1, timeout=None):
        return self._ele(locator, timeout, index=index, method='ele()')

    def eles(self, locator, timeout=None):
        return self._ele(locator, timeout=timeout, index=None)

    def s_ele(self, locator=None, index=1, timeout=None):
        return (make_session_ele(self, locator, index=index, method='s_ele()')
                if locator is None or self.ele(locator, index=index, timeout=timeout)
                else NoneElement(self.owner, method='s_ele()', args={'locator': locator, 'index': index}))

    def s_eles(self, locator=None, timeout=None):
        return (make_session_ele(self, locator, index=None)
                if self.ele(locator, timeout=timeout) else SessionElementsList())

    def _find_elements(self, locator, timeout, index=1, relative=False, raise_err=None):
        return find_in_chromium_ele(self, locator, index, timeout, relative=relative)

    def style(self, style, pseudo_ele=''):
        if pseudo_ele:
            pseudo_ele = f', "{pseudo_ele}"'
        return self._run_js(f'return window.getComputedStyle(this{pseudo_ele}).getPropertyValue("{style}");')

    def src(self, timeout=None, base64_to_bytes=True):
        if timeout is None:
            timeout = self.timeout
        if self.tag == 'img':  # 等待图片加载完成
            js = ('return this.complete && typeof this.naturalWidth != "undefined" '
                  '&& this.naturalWidth > 0 && typeof this.naturalHeight != "undefined" '
                  '&& this.naturalHeight > 0')
            end_time = perf_counter() + timeout
            while not self._run_js(js) and perf_counter() < end_time:
                sleep(.05)

        src = self.attr('href') if self.tag == 'link' else self.attr('src')
        if not src:
            raise RuntimeError(_S._lang.join(_S._lang.NO_SRC_ATTR))
        if src.lower().startswith('data:image'):
            if base64_to_bytes:
                from base64 import b64decode
                return b64decode(src.split(',', 1)[-1])
            else:
                return src.split(',', 1)[-1]

        is_blob = src.startswith('blob')
        result = None
        end_time = perf_counter() + timeout
        if is_blob:
            while perf_counter() < end_time:
                result = get_blob(self.owner, src, base64_to_bytes)
                if result:
                    break
                sleep(.05)

        else:
            while perf_counter() < end_time:
                src = self.attr('href') if self.tag == 'link' else self.property('currentSrc') or self.property('src')
                if not src:
                    sleep(.01)
                    continue

                node = self.owner._run_cdp('DOM.describeNode', backendNodeId=self._backend_id)['node']
                frame = node.get('frameId', None) or self.owner._frame_id

                try:
                    result = self.owner._run_cdp('Page.getResourceContent', frameId=frame, url=src)
                    break
                except CDPError:
                    pass
                sleep(.05)

        if not result:
            return None

        elif is_blob:
            return result

        elif result['base64Encoded'] and base64_to_bytes:
            from base64 import b64decode
            return b64decode(result['content'])
        else:
            return result['content']

    def save(self, path=None, name=None, timeout=None, rename=True):
        data = self.src(timeout=timeout)
        if not data:
            raise NoResourceError

        path = path or '.'
        if not name and self.tag == 'img':
            src = self.attr('src')
            if src.lower().startswith('data:image'):
                r = search(r'data:image/(.*?);base64,', src)
                name = f'img.{r.group(1)}' if r else None
        path = Path(path) / make_valid_name(name or basename(self.property('currentSrc')))
        if not path.suffix:
            path = path.with_suffix('.jpg')
        if rename:
            path = get_usable_path(path)
        path.parent.mkdir(parents=True, exist_ok=True)
        path = path.absolute()
        write_type = 'wb' if isinstance(data, bytes) else 'w'

        with open(path, write_type) as f:
            f.write(data)

        return str(path)

    def get_screenshot(self, path=None, name=None, as_bytes=None, as_base64=None, scroll_to_center=True):
        if self.tag == 'img':  # 等待图片加载完成
            js = ('return this.complete && typeof this.naturalWidth != "undefined" && this.naturalWidth > 0 '
                  '&& typeof this.naturalHeight != "undefined" && this.naturalHeight > 0')
            end_time = perf_counter() + self.timeout
            while not self._run_js(js) and perf_counter() < end_time:
                sleep(.05)
        if scroll_to_center:
            self.scroll.to_see(center=True)

        left, top = self.rect.location
        width, height = self.rect.size
        left_top = (left, top)
        right_bottom = (left + width, top + height)
        if not name:
            name = f'{self.tag}.jpg'

        return self.owner._get_screenshot(path, name, as_bytes=as_bytes, as_base64=as_base64, full_page=False,
                                          left_top=left_top, right_bottom=right_bottom, ele=self)

    def input(self, vals, clear=False, by_js=False):
        if self.tag == 'input' and self.attr('type') == 'file':
            return self._set_file_input(vals)

        if by_js:
            if clear:
                self.clear(True)
            if isinstance(vals, (list, tuple)):
                vals = ''.join([str(i) for i in vals])
            self.set.property('value', str(vals))
            self._run_js('this.dispatchEvent(new Event("change", {bubbles: true}));')
            return self

        self.wait.clickable(wait_moved=False, timeout=.5)
        if clear and vals not in ('\n', '\ue007', '\ue006'):
            self.clear(by_js=False)
        else:
            self._input_focus()

        if isinstance(vals, str) and vals not in ('\ue003', '\ue017', '\ue010', '\ue011',
                                                  '\ue012', '\ue013', '\ue014', '\ue015',):
            input_text_or_keys(self.owner, vals)
        else:
            self.owner.actions.type(vals)

        return self

    def clear(self, by_js=False):
        if by_js or system().lower() in ('macos', 'darwin'):
            self._run_js("this.value='';")
            self._run_js('this.dispatchEvent(new Event("change", {bubbles: true}));')
            return self

        self._input_focus()
        self.input((Keys.CTRL_A, Keys.DEL), clear=False)
        return self

    def _input_focus(self):
        try:
            self.owner._run_cdp('DOM.focus', backendNodeId=self._backend_id)
        except Exception:
            self.click(by_js=None)

    def focus(self):
        try:
            self.owner._run_cdp('DOM.focus', backendNodeId=self._backend_id)
        except Exception:
            self._run_js('this.focus();')
        return self

    def hover(self, offset_x=None, offset_y=None):
        self.owner.actions.move_to(self, offset_x=offset_x, offset_y=offset_y, duration=.1)
        return self

    def drag(self, offset_x=0, offset_y=0, duration=.5):
        curr_x, curr_y = self.rect.midpoint
        offset_x += curr_x
        offset_y += curr_y
        self.drag_to((offset_x, offset_y), duration)
        return self

    def drag_to(self, ele_or_loc, duration=.5):
        if isinstance(ele_or_loc, ChromiumElement):
            ele_or_loc = ele_or_loc.rect.midpoint
        elif not isinstance(ele_or_loc, (list, tuple)):
            raise ValueError(_S._lang.join(_S._lang.INCORRECT_TYPE_, 'ele_or_loc',
                                           ALLOW_TYPE=_S._lang.ELE_LOC_FORMAT, CURR_VAL=ele_or_loc))
        self.owner.actions.hold(self).move_to(ele_or_loc, duration=duration).release()
        return self

    def _get_obj_id(self, node_id=None, backend_id=None):
        if node_id:
            return self.owner._run_cdp('DOM.resolveNode', nodeId=node_id)['object']['objectId']
        else:
            return self.owner._run_cdp('DOM.resolveNode', backendNodeId=backend_id)['object']['objectId']

    def _get_node_id(self, obj_id=None, backend_id=None):
        if obj_id:
            return self.owner._run_cdp('DOM.requestNode', objectId=obj_id)['nodeId']
        else:
            n = self.owner._run_cdp('DOM.describeNode', backendNodeId=backend_id)['node']
            self._tag = n['localName']
            return n['nodeId']

    def _get_backend_id(self, node_id):
        n = self.owner._run_cdp('DOM.describeNode', nodeId=node_id)['node']
        self._tag = n['localName']
        return n['backendNodeId']

    def _refresh_id(self):
        self._obj_id = self._get_obj_id(backend_id=self._backend_id)
        self._node_id = self._get_node_id(obj_id=self._obj_id)

    def _get_ele_path(self, xpath=True):
        if xpath:
            txt1 = 'let tag = el.nodeName.toLowerCase();'
            txt3 = ''' && sib.nodeName.toLowerCase()===tag'''
            txt4 = '''path = '/' + tag + '[' + nth + ']' + path;'''
            txt5 = '''return path;'''

        else:
            txt1 = '''
            let i = el.getAttribute("id");
            if (i){path = '>' + el.tagName.toLowerCase() + "#" + i + path;
            el = el.parentNode;
            continue;}
            '''
            txt3 = ''
            txt4 = '''path = '>' + el.tagName.toLowerCase() + ":nth-child(" + nth + ")" + path;'''
            txt5 = '''return path.substr(1);'''

        js = '''function(){
        function e(el) {
            if (!(el instanceof Element)) return;
            let path = '';
            while (el.nodeType === Node.ELEMENT_NODE) {
                ''' + txt1 + '''
                    let sib = el, nth = 0;
                    while (sib) {
                        if(sib.nodeType === Node.ELEMENT_NODE''' + txt3 + '''){nth += 1;}
                        sib = sib.previousSibling;
                    }
                    ''' + txt4 + '''
                el = el.parentNode;
            }
            ''' + txt5 + '''
        }
        return e(this);}
        '''
        return self._run_js(js)

    def _set_file_input(self, files):
        if isinstance(files, str):
            files = files.split('\n')
        files = [str(Path(i).absolute()) for i in files]
        self.owner._run_cdp('DOM.setFileInputFiles', files=files, backendNodeId=self._backend_id)
        return self


class ShadowRoot(BaseElement):

    def __init__(self, parent_ele, obj_id=None, backend_id=None):
        super().__init__(parent_ele.owner)
        self.tab = self.owner._tab
        self.parent_ele = parent_ele
        if backend_id:
            self._backend_id = backend_id
            self._obj_id = self._get_obj_id(backend_id)
            self._node_id = self._get_node_id(self._obj_id)
        elif obj_id:
            self._obj_id = obj_id
            self._node_id = self._get_node_id(obj_id)
            self._backend_id = self._get_backend_id(self._node_id)
        self._states = None
        self._type = 'ShadowRoot'

    def __call__(self, locator, index=1, timeout=None):
        return self.ele(locator, index=index, timeout=timeout)

    def __repr__(self):
        return f'<ShadowRoot in {self.parent_ele}>'

    def __eq__(self, other):
        return self._backend_id == getattr(other, '_backend_id', None)

    @property
    def tag(self):
        return 'shadow-root'

    @property
    def html(self):
        return f'<shadow_root>{self.inner_html}</shadow_root>'

    @property
    def inner_html(self):
        return self._run_js('return this.innerHTML;')

    @property
    def states(self):
        if self._states is None:
            self._states = ShadowRootStates(self)
        return self._states

    def run_js(self, script, *args, as_expr=False, timeout=None):
        return self._run_js(script, *args, as_expr=as_expr, timeout=timeout)

    def _run_js(self, script, *args, as_expr=False, timeout=None):
        return run_js(self, script, as_expr, self.owner.timeouts.script if timeout is None else timeout, args)

    def run_async_js(self, script, *args, as_expr=False, timeout=None):
        from threading import Thread
        Thread(target=run_js, args=(self, script, as_expr,
                                    self.owner.timeouts.script if timeout is None else timeout, args)).start()

    def parent(self, level_or_loc=1, index=1, timeout=0):
        if isinstance(level_or_loc, int):
            loc = f'xpath:./ancestor-or-self::*[{level_or_loc}]'

        elif isinstance(level_or_loc, (tuple, str)):
            loc = get_loc(level_or_loc, True)

            if loc[0] == 'css selector':
                raise LocatorError(_S._lang.UNSUPPORTED_CSS_SYNTAX)

            loc = f'xpath:./ancestor-or-self::{loc[1].lstrip(". / ")}[{index}]'

        else:
            raise ValueError(_S._lang.join(_S._lang.INCORRECT_TYPE_, 'level_or_loc',
                                           ALLOW_TYPE=_S._lang.LOC_OR_IND, CURR_VAL=level_or_loc))

        return self.parent_ele._ele(loc, timeout=timeout, relative=True, raise_err=False, method='parent()')

    def child(self, locator='', index=1, timeout=None):
        if not locator:
            loc = '*'
        else:
            loc = get_loc(locator, True)  # 把定位符转换为xpath
            if loc[0] == 'css selector':
                raise LocatorError(_S._lang.UNSUPPORTED_CSS_SYNTAX)
            loc = loc[1].lstrip('./')

        loc = f'xpath:./{loc}'
        ele = self._ele(loc, index=index, relative=True, timeout=timeout)

        return ele if ele else NoneElement(self.owner, 'child()',
                                           {'locator': locator, 'index': index, 'timeout': timeout})

    def next(self, locator='', index=1, timeout=None):
        loc = get_loc(locator, True)
        if loc[0] == 'css selector':
            raise LocatorError(_S._lang.UNSUPPORTED_CSS_SYNTAX)

        loc = loc[1].lstrip('./')
        xpath = f'xpath:./{loc}'
        ele = self.parent_ele._ele(xpath, index=index, relative=True, timeout=timeout)

        return ele if ele else NoneElement(self.owner, 'next()',
                                           {'locator': locator, 'index': index, 'timeout': timeout})

    def before(self, locator='', index=1, timeout=None):
        loc = get_loc(locator, True)
        if loc[0] == 'css selector':
            raise LocatorError(_S._lang.UNSUPPORTED_CSS_SYNTAX)

        loc = loc[1].lstrip('./')
        xpath = f'xpath:./preceding::{loc}'
        ele = self.parent_ele._ele(xpath, index=index, relative=True, timeout=timeout)

        return ele if ele else NoneElement(self.owner, 'before()',
                                           {'locator': locator, 'index': index, 'timeout': timeout})

    def after(self, locator='', index=1, timeout=None):
        nodes = self.afters(locator=locator, timeout=timeout)
        return nodes[index - 1] if nodes else NoneElement(self.owner, 'after()',
                                                          {'locator': locator, 'index': index, 'timeout': timeout})

    def children(self, locator='', timeout=None):
        if not locator:
            loc = '*'
        else:
            loc = get_loc(locator, True)  # 把定位符转换为xpath
            if loc[0] == 'css selector':
                raise LocatorError(_S._lang.UNSUPPORTED_CSS_SYNTAX)
            loc = loc[1].lstrip('./')

        loc = f'xpath:./{loc}'
        return self._ele(loc, index=None, relative=True, timeout=timeout)

    def nexts(self, locator='', timeout=None):
        loc = get_loc(locator, True)
        if loc[0] == 'css selector':
            raise LocatorError(_S._lang.UNSUPPORTED_CSS_SYNTAX)

        loc = loc[1].lstrip('./')
        xpath = f'xpath:./{loc}'
        return self.parent_ele._ele(xpath, index=None, relative=True, timeout=timeout)

    def befores(self, locator='', timeout=None):
        loc = get_loc(locator, True)
        if loc[0] == 'css selector':
            raise LocatorError(_S._lang.UNSUPPORTED_CSS_SYNTAX)

        loc = loc[1].lstrip('./')
        xpath = f'xpath:./preceding::{loc}'
        return self.parent_ele._ele(xpath, index=None, relative=True, timeout=timeout)

    def afters(self, locator='', timeout=None):
        eles1 = self.nexts(locator)
        loc = get_loc(locator, True)[1].lstrip('./')
        xpath = f'xpath:./following::{loc}'
        return eles1 + self.parent_ele._ele(xpath, index=None, relative=True, timeout=timeout)

    def ele(self, locator, index=1, timeout=None):
        return self._ele(locator, timeout, index=index, method='ele()')

    def eles(self, locator, timeout=None):
        return self._ele(locator, timeout=timeout, index=None)

    def s_ele(self, locator=None, index=1, timeout=None):
        return (make_session_ele(self, locator, index=index, method='s_ele()')
                if locator is None or self.ele(locator, index=index, timeout=timeout)
                else NoneElement(self.owner, method='s_ele()', args={'locator': locator, 'index': index}))

    def s_eles(self, locator, timeout=None):
        return (make_session_ele(self, locator, index=None)
                if self.ele(locator, timeout=timeout) else SessionElementsList())

    def _find_elements(self, locator, timeout, index=1, relative=False, raise_err=None):
        loc = get_loc(locator, css_mode=False)
        if loc[0] == 'css selector' and str(loc[1]).startswith(':root'):
            loc = loc[0], loc[1][5:]

        def do_find():
            if loc[0] == 'css selector':
                if index == 1:
                    nod_id = self.owner._run_cdp('DOM.querySelector', nodeId=self._node_id, selector=loc[1])['nodeId']
                    if nod_id:
                        r = make_chromium_eles(self.owner, _ids=nod_id, is_obj_id=False)
                        return None if r is False else r

                else:
                    nod_ids = self.owner._run_cdp('DOM.querySelectorAll',
                                                  nodeId=self._node_id, selector=loc[1])['nodeIds']
                    r = make_chromium_eles(self.owner, _ids=nod_ids, index=index, is_obj_id=False)
                    return None if r is False else r

            else:
                eles = make_session_ele(self, loc, index=None)
                if isinstance(eles, (float, str, int)):
                    return eles
                elif not eles:
                    return None

                css = []
                for i in eles:
                    if hasattr(i, 'css_path'):
                        c = i.css_path
                        if c in ('html:nth-child(1)', 'html:nth-child(1)>body:nth-child(1)',
                                 'html:nth-child(1)>body:nth-child(1)>shadow_root:nth-child(1)'):
                            continue
                        elif c.startswith('html:nth-child(1)>body:nth-child(1)>shadow_root:nth-child(1)'):
                            c = c[61:]
                        css.append((True, c))

                    else:
                        css.append((False, i))

                if index is not None:
                    try:
                        c = css[index - 1]
                        if c[0] is False:
                            return c[1]
                        node_id = self.owner._run_cdp('DOM.querySelector', nodeId=self._node_id,
                                                      selector=c[1])['nodeId']
                        r = make_chromium_eles(self.owner, _ids=node_id, is_obj_id=False)
                        return None if r is False else r

                    except IndexError:
                        return None

                else:
                    r = []
                    for i in css:
                        if i[0] is False:
                            r.append(i[1])

                        else:
                            node_id = self.owner._run_cdp('DOM.querySelector', nodeId=self._node_id,
                                                          selector=i[1])['nodeId']
                            if node_id:
                                e = make_chromium_eles(self.owner, _ids=node_id, is_obj_id=False)
                                if e is False:
                                    return None
                                r.append(e)

                    return None if not r else r

        end_time = perf_counter() + timeout
        result = do_find()
        while result is None and perf_counter() <= end_time:
            sleep(.01)
            result = do_find()

        if result or isinstance(result, (str, float, int)):
            return result
        return NoneElement(self.owner) if index is not None else ChromiumElementsList(self.owner)

    def _get_node_id(self, obj_id):
        return self.owner._run_cdp('DOM.requestNode', objectId=obj_id)['nodeId']

    def _get_obj_id(self, back_id):
        return self.owner._run_cdp('DOM.resolveNode', backendNodeId=back_id)['object']['objectId']

    def _get_backend_id(self, node_id):
        r = self.owner._run_cdp('DOM.describeNode', nodeId=node_id)['node']
        self._tag = r['localName'].lower()
        return r['backendNodeId']


def find_in_chromium_ele(ele, locator, index=1, timeout=None, relative=True):
    # ---------------处理定位符---------------
    if isinstance(locator, (str, tuple)):
        loc = get_loc(locator)
    else:
        raise LocatorError(ALLOW_TYPE=_S._lang.LOC_FORMAT, CURR_VAL=locator)

    loc_str = loc[1]
    if loc[0] == 'xpath' and loc[1].lstrip().startswith('/'):
        loc_str = f'.{loc_str}'
    elif loc[0] == 'css selector' and loc[1].lstrip().startswith('>'):
        loc_str = f'{ele.css_path}{loc[1]}'
    loc = loc[0], loc_str

    if timeout is None:
        timeout = ele.timeout

    # ---------------执行查找-----------------
    if loc[0] == 'xpath':
        return find_by_xpath(ele, loc[1], index, timeout, relative=relative)

    else:
        return find_by_css(ele, loc[1], index, timeout)


def find_by_xpath(ele, xpath, index, timeout, relative=True):
    type_txt = '9' if index == 1 else '7'
    node_txt = 'this.contentDocument' if ele.tag in __FRAME_ELEMENT__ and not relative else 'this'
    js = make_js_for_find_ele_by_xpath(xpath, type_txt, node_txt)
    ele.owner.wait.doc_loaded()

    def do_find():
        res = ele.owner._run_cdp('Runtime.callFunctionOn', functionDeclaration=js, objectId=ele._obj_id,
                                 returnByValue=False, awaitPromise=True, userGesture=True)
        if res['result']['type'] == 'string':
            return res['result']['value']
        if 'exceptionDetails' in res:
            if 'The result is not a node set' in res['result']['description']:
                js1 = make_js_for_find_ele_by_xpath(xpath, '1', node_txt)
                res = ele.owner._run_cdp('Runtime.callFunctionOn', functionDeclaration=js1, objectId=ele._obj_id,
                                         returnByValue=False, awaitPromise=True, userGesture=True)
                return res['result']['value']
            elif 'is not a valid XPath expression' in res['result']['description']:
                raise LocatorError(_S._lang.INVALID_XPATH_, xpath)
            else:
                raise LocatorError(_S._lang.FIND_ELE_ERR, INFO=res)

        if res['result']['subtype'] == 'null' or res['result']['description'] in ('NodeList(0)', 'Array(0)'):
            return None

        if index == 1:
            r = make_chromium_eles(ele.owner, _ids=res['result']['objectId'], is_obj_id=True)
            return None if r is False else r

        else:
            res = ele.owner._run_cdp('Runtime.getProperties', objectId=res['result']['objectId'],
                                     ownProperties=True)['result'][:-1]
            if index is None:
                r = ChromiumElementsList(owner=ele.owner)
                for i in res:
                    if i['value']['type'] == 'object':
                        r.append(make_chromium_eles(ele.owner, _ids=i['value']['objectId'], is_obj_id=True))
                    else:
                        r.append(i['value']['value'])
                return None if False in r else r

            else:
                eles_count = len(res)
                if eles_count == 0 or abs(index) > eles_count:
                    return None

                index1 = eles_count + index + 1 if index < 0 else index
                res = res[index1 - 1]
                if res['value']['type'] == 'object':
                    r = make_chromium_eles(ele.owner, _ids=res['value']['objectId'], is_obj_id=True)
                else:
                    r = res['value']['value']
                return None if r is False else r

    end_time = perf_counter() + timeout
    result = do_find()
    while result is None and perf_counter() < end_time:
        sleep(.01)
        result = do_find()

    if result:
        return result
    return NoneElement(ele.owner) if index is not None else ChromiumElementsList(owner=ele.owner)


def find_by_css(ele, selector, index, timeout):
    selector = selector.replace('"', r'\"')
    find_all = '' if index == 1 else 'All'
    node_txt = 'this.contentDocument' if ele.tag in ('iframe', 'frame', 'shadow-root') else 'this'
    js = f'function(){{return {node_txt}.querySelector{find_all}("{selector}");}}'

    ele.owner.wait.doc_loaded()

    def do_find():
        res = ele.owner._run_cdp('Runtime.callFunctionOn', functionDeclaration=js, objectId=ele._obj_id,
                                 returnByValue=False, awaitPromise=True, userGesture=True)

        if 'exceptionDetails' in res:
            if 'is not a valid selector' in res['result']['description']:
                raise LocatorError(_S._lang.INVALID_CSS_, selector)
            else:
                raise LocatorError(_S._lang.FIND_ELE_ERR, INFO=res)
        if res['result']['subtype'] == 'null' or res['result']['description'] in ('NodeList(0)', 'Array(0)'):
            return None

        if index == 1:
            r = make_chromium_eles(ele.owner, _ids=res['result']['objectId'], is_obj_id=True)
            return None if r is False else r

        else:
            obj_ids = [i['value']['objectId'] for i in ele.owner._run_cdp('Runtime.getProperties',
                                                                          objectId=res['result']['objectId'],
                                                                          ownProperties=True)['result']]
            r = make_chromium_eles(ele.owner, _ids=obj_ids, index=index, is_obj_id=True)
            return None if r is False else r

    end_time = perf_counter() + timeout
    result = do_find()
    while result is None and perf_counter() < end_time:
        sleep(.01)
        result = do_find()

    if result:
        return result
    return NoneElement(ele.owner) if index is not None else ChromiumElementsList(owner=ele.owner)


def make_chromium_eles(page, _ids, index=1, is_obj_id=True, ele_only=False):
    if is_obj_id:
        get_node_func = _get_node_by_obj_id
    else:
        get_node_func = _get_node_by_node_id
    if not isinstance(_ids, (list, tuple)):
        _ids = (_ids,)

    if index is not None:  # 获取一个
        if ele_only:
            for obj_id in _ids:
                tmp = get_node_func(page, obj_id, ele_only)
                if tmp is not None:
                    return tmp
            return False

        else:
            obj_id = _ids[index - 1]
            return get_node_func(page, obj_id, ele_only)

    else:  # 获取全部
        nodes = ChromiumElementsList(owner=page)
        for obj_id in _ids:
            # if obj_id == 0:
            #     continue
            tmp = get_node_func(page, obj_id, ele_only)
            if tmp is False:
                return False
            elif tmp is not None:
                nodes.append(tmp)
        return nodes


def _get_node_info(page, id_type, _id):
    if not _id:
        return False
    arg = {id_type: _id}
    node = page.driver.run('DOM.describeNode', **arg)
    if 'error' in node:
        return False
    return node


def _get_node_by_obj_id(page, obj_id, ele_only):
    """根据obj id返回元素对象或文本,ele_only时如果是文本返回None,出错返回False"""
    node = _get_node_info(page, 'objectId', obj_id)
    if node is False:
        return False
    if node['node']['nodeName'] in ('#text', '#comment'):
        return None if ele_only else node['node']['nodeValue']
    else:
        return _make_ele(page, obj_id, node)


def _get_node_by_node_id(page, node_id, ele_only):
    """根据node id返回元素对象或文本,ele_only时如果是文本返回None,出错返回False"""
    node = _get_node_info(page, 'nodeId', node_id)
    if node is False:
        return False
    if node['node']['nodeName'] in ('#text', '#comment'):
        return None if ele_only else node['node']['nodeValue']
    else:
        obj_id = page.driver.run('DOM.resolveNode', nodeId=node_id)
        if 'error' in obj_id:
            return False
        obj_id = obj_id['object']['objectId']
        return _make_ele(page, obj_id, node)


def _make_ele(page, obj_id, node):
    ele = ChromiumElement(page, obj_id=obj_id, node_id=node['node']['nodeId'],
                          backend_id=node['node']['backendNodeId'])
    if ele.tag in __FRAME_ELEMENT__:
        from .._pages.chromium_frame import ChromiumFrame
        ele = ChromiumFrame(page, ele, node)
    return ele


def make_js_for_find_ele_by_xpath(xpath, type_txt, node_txt):
    for_txt = ''

    # 获取第一个元素、节点或属性
    if type_txt == '9':
        return_txt = '''
if(e.singleNodeValue==null){return null;}
else if(e.singleNodeValue.constructor.name=="Text"){return e.singleNodeValue.data;}
else if(e.singleNodeValue.constructor.name=="Attr"){return e.singleNodeValue.nodeValue;}
else if(e.singleNodeValue.constructor.name=="Comment"){return e.singleNodeValue.nodeValue;}
else{return e.singleNodeValue;}'''

    # 按顺序获取所有元素、节点或属性
    elif type_txt == '7':
        for_txt = """
let a=new Array();
for(let i = 0; i <e.snapshotLength ; i++){
if(e.snapshotItem(i).constructor.name=="Text"){a.push(e.snapshotItem(i).data);}
else if(e.snapshotItem(i).constructor.name=="Attr"){a.push(e.snapshotItem(i).nodeValue);}
else if(e.snapshotItem(i).constructor.name=="Comment"){a.push(e.snapshotItem(i).nodeValue);}
else{a.push(e.snapshotItem(i));}}"""
        return_txt = 'return a;'

    elif type_txt == '2':
        return_txt = 'return e.stringValue;'
    elif type_txt == '1':
        return_txt = 'return e.numberValue;'
    else:
        return_txt = 'return e.singleNodeValue;'

    xpath = xpath.replace(r"'", r"\'")
    js = f'function(){{let e=document.evaluate(\'{xpath}\',{node_txt},null,{type_txt},null);\n{for_txt}\n{return_txt}}}'

    return js


def run_js(page_or_ele, script, as_expr, timeout, args=None):
    if isinstance(page_or_ele, (ChromiumElement, ShadowRoot)):
        is_page = False
        page = page_or_ele.owner
        obj_id = page_or_ele._obj_id
    else:
        is_page = True
        page = page_or_ele
        end_time = perf_counter() + 5
        while perf_counter() < end_time:
            obj_id = page_or_ele._root_id
            if obj_id is not None:
                break
            sleep(.01)
        else:
            raise RuntimeError(_S._lang.join(_S._lang.JS_RUNTIME_ERR))

    if page.states.has_alert:
        raise AlertExistsError

    try:
        if Path(script).exists():
            with open(script, 'r', encoding='utf-8') as f:
                script = f.read()
    except (OSError, ValueError):
        pass

    end_time = perf_counter() + timeout
    try:
        if as_expr:
            res = page._run_cdp('Runtime.evaluate', expression=script, returnByValue=False,
                                awaitPromise=True, userGesture=True, _timeout=timeout, _ignore=AlertExistsError)

        else:
            args = args or ()
            if not is_js_func(script):
                script = f'function(){{{script}}}'
            res = page._run_cdp('Runtime.callFunctionOn', functionDeclaration=script, objectId=obj_id,
                                arguments=[convert_argument(arg) for arg in args], returnByValue=False,
                                awaitPromise=True, userGesture=True, _timeout=timeout, _ignore=AlertExistsError)
    except TimeoutError:
        raise TimeoutError(_S._lang.join(_S._lang.TIMEOUT_, _S._lang.RUN_JS, timeout))
    except ContextLostError:
        raise ContextLostError() if is_page else ElementLostError()

    if not res:  # _timeout=0或js激活alert时
        return None

    exceptionDetails = res.get('exceptionDetails')
    if exceptionDetails:
        raise JavaScriptError(JS=script, INFO=exceptionDetails)

    try:
        return parse_js_result(page, page_or_ele, res.get('result'), end_time)
    except Exception:
        from DrissionPage import __version__
        raise RuntimeError(_S._lang.join(_S._lang.JS_RESULT_ERR, INFO=res, JS=script, TIP=_S._lang.FEEDBACK))


def parse_js_result(page, ele, result, end_time):
    if 'unserializableValue' in result:
        return result['unserializableValue']

    the_type = result['type']
    if the_type == 'object':
        sub_type = result.get('subtype', None)
        if sub_type == 'null':
            return None

        elif sub_type == 'node':
            class_name = result['className']
            if class_name == 'ShadowRoot':
                return ShadowRoot(ele, obj_id=result['objectId'])
            elif class_name == 'HTMLDocument':
                return result
            else:
                r = make_chromium_eles(page, _ids=result['objectId'])
                if r is False:
                    raise ElementLostError
                return r

        elif sub_type == 'array':
            r = page._run_cdp('Runtime.getProperties', objectId=result['objectId'], ownProperties=True)['result']
            return [parse_js_result(page, ele, result=i['value'], end_time=end_time) for i in r if i['name'].isdigit()]

        elif result.get('className') == 'Blob':
            data = page._run_cdp('IO.read',
                                 handle=f"blob:{page._run_cdp('IO.resolveBlob', objectId=result['objectId'])['uuid']}")[
                'data']
            return data

        elif 'objectId' in result:
            timeout = end_time - perf_counter()
            if timeout < 0:
                return
            js = 'function(){return JSON.stringify(this);}'
            r = page._run_cdp('Runtime.callFunctionOn', functionDeclaration=js, objectId=result['objectId'],
                              returnByValue=False, awaitPromise=True, userGesture=True, _ignore=AlertExistsError,
                              _timeout=timeout)
            return loads(parse_js_result(page, ele, r['result'], end_time))

        else:
            return result.get('value', result)

    elif the_type == 'undefined':
        return None

    elif the_type == 'function':
        return result['description']

    else:
        return result['value']


def convert_argument(arg):
    if isinstance(arg, ChromiumElement):
        return {'objectId': arg._obj_id}

    elif isinstance(arg, (int, float, str, bool, dict)):
        return {'value': arg}

    from math import inf
    if arg == inf:
        return {'unserializableValue': 'Infinity'}
    elif arg == -inf:
        return {'unserializableValue': '-Infinity'}

    raise TypeError(_S._lang.join(_S._lang.UNSUPPORTED_ARG_TYPE_, arg, type(arg)))


class Pseudo(object):
    def __init__(self, ele):
        self._ele = ele

    @property
    def before(self):
        for i in ('::before', ':before', 'before'):
            r = self._ele.style('content', i)
            if r != 'content':
                return r
        return r

    @property
    def after(self):
        for i in ('::after', ':after', 'after'):
            r = self._ele.style('content', i)
            if r != 'content':
                return r
        return r


def _check_ele(ele, loc_data):
    """检查元素是否符合loc_data指定的要求
    :param ele: 元素对象
    :param loc_data: 格式: {'and': bool, 'args': ['属性名称', '匹配方式', '属性值', 是否否定]}
    :return: bool
    """
    attrs = ele.attrs
    if loc_data['and']:
        ok = True
        for i in loc_data['args']:
            name, symbol, value, deny = i
            if name == 'tag()':
                arg = ele.tag
                symbol = '='
            elif name == 'text()':
                arg = ele.raw_text
            elif name is None:
                arg = None
            else:
                arg = attrs.get(name, '')

            if ((symbol == '=' and ((deny and arg == value) or (not deny and arg != value)))
                    or (symbol == ':' and ((deny and value in arg) or (not deny and value not in arg)))
                    or (symbol == '^' and ((deny and arg.startswith(value))
                                           or (not deny and not arg.startswith(value))))
                    or (symbol == '$' and ((deny and arg.endswith(value)) or (not deny and not arg.endswith(value))))
                    or (arg is None and attrs)):
                ok = False
                break

    else:
        ok = False
        for i in loc_data['args']:
            name, value, symbol, deny = i
            if name == 'tag()':
                arg = ele.tag
                symbol = '='
            elif name == 'text()':
                arg = ele.text
            elif name is None:
                arg = None
            else:
                arg = attrs.get(name, '')

            if ((symbol == '=' and ((not deny and arg == value) or (deny and arg != value)))
                    or (symbol == ':' and ((not deny and value in arg) or (deny and value not in arg)))
                    or (symbol == '^' and ((not deny and arg.startswith(value))
                                           or (deny and not arg.startswith(value))))
                    or (symbol == '$' and ((not deny and arg.endswith(value)) or (deny and not arg.endswith(value))))
                    or (arg is None and not attrs)):
                ok = True
                break

    return ok


================================================
FILE: DrissionPage/_elements/chromium_element.pyi
================================================
# -*- coding:utf-8 -*-
"""
@Author   : g1879
@Contact  : g1879@qq.com
@Website  : https://DrissionPage.cn
@Copyright: (c) 2020 by g1879, Inc. All Rights Reserved.
"""
from pathlib import Path
from typing import Union, Tuple, List, Any, Literal, Optional

from .._base.base import DrissionElement, BaseElement
from .._elements.session_element import SessionElement
from .._functions.elements import SessionElementsList, ChromiumElementsList
from .._pages.chromium_base import ChromiumBase
from .._pages.chromium_frame import ChromiumFrame
from .._pages.chromium_page import ChromiumPage
from .._pages.chromium_tab import ChromiumTab
from .._pages.web_page import WebPage
from .._units.clicker import Clicker
from .._units.rect import ElementRect
from .._units.scroller import ElementScroller
from .._units.selector import SelectElement
from .._units.setter import ChromiumElementSetter
from .._units.states import ShadowRootStates, ElementStates
from .._units.waiter import ElementWaiter

PIC_TYPE = Literal['jpg', 'jpeg', 'png', 'webp', True]


class ChromiumElement(DrissionElement):
    _tag: Optional[str] = ...
    owner: ChromiumBase = ...
    page: Union[ChromiumPage, WebPage] = ...
    tab: Union[ChromiumPage, ChromiumTab] = ...
    _node_id: int = ...
    _obj_id: str = ...
    _backend_id: int = ...
    _doc_id: Optional[str] = ...
    _scroll: Optional[ElementScroller] = ...
    _clicker: Optional[Clicker] = ...
    _select: Union[SelectElement, None, False] = ...
    _wait: Optional[ElementWaiter] = ...
    _rect: Optional[ElementRect] = ...
    _set: Optional[ChromiumElementSetter] = ...
    _states: Optional[ElementStates] = ...
    _pseudo: Optional[Pseudo] = ...

    def __init__(self,
                 owner: ChromiumBase,
                 node_id: int = None,
                 obj_id: str = None,
                 backend_id: int = None):
        """node_id、obj_id和backend_id必须至少传入一个
        :param owner: 元素所在页面对象
        :param node_id: cdp中的node id
        :param obj_id: js中的object id
        :param backend_id: backend id
        """
        ...

    def __call__(self,
                 locator: Union[Tuple[str, str], str],
                 index: int = 1,
                 timeout: float = None) -> ChromiumElement:
        """在内部查找元素
        :param locator: 元素的定位信息,可以是loc元组,或查询字符串
        :param timeout: 超时时间(秒)
        :return: ChromiumElement对象或属性、文本
        """
        ...

    def __repr__(self) -> str: ...

    def __eq__(self, other: ChromiumElement) -> bool: ...

    @property
    def tag(self) -> str:
        """返回元素tag"""
        ...

    @property
    def html(self) -> str:
        """返回元素outerHTML文本"""
        ...

    @property
    def inner_html(self) -> str:
        """返回元素innerHTML文本"""
        ...

    @property
    def attrs(self) -> dict:
        """返回元素所有attribute属性"""
        ...

    @property
    def text(self) -> str:
        """返回元素内所有文本,文本已格式化"""
        ...

    @property
    def raw_text(self) -> str:
        """返回未格式化处理的元素内文本"""
        ...

    @property
    def set(self) -> ChromiumElementSetter:
        """返回用于设置元素属性的对象"""
        ...

    @property
    def states(self) -> ElementStates:
        """返回用于获取元素状态的对象"""
        ...

    @property
    def pseudo(self) -> Pseudo:
        """返回用于获取伪元素内容的对象"""
        ...

    @property
    def rect(self) -> ElementRect:
        """返回用于获取元素位置的对象"""
        ...

    @property
    def shadow_root(self) -> Union[None, ShadowRoot]:
        """返回当前元素的shadow_root元素对象"""
        ...

    @property
    def sr(self) -> Union[None, ShadowRoot]:
        """返回当前元素的shadow_root元素对象"""
        ...

    @property
    def scroll(self) -> ElementScroller:
        """用于滚动滚动条的对象"""
        ...

    @property
    def click(self) -> Clicker:
        """返回用于点击的对象"""
        ...

    @property
    def wait(self) -> ElementWaiter:
        """返回用于等待的对象"""
        ...

    @property
    def select(self) -> Union[SelectElement, False]:
        """返回专门处理下拉列表的Select类,非<select>元素返回False"""
        ...

    @property
    def value(self) -> str:
        """返回元素property属性的value值"""
        ...

    def parent(self,
               level_or_loc: Union[tuple, str, int] = 1,
               index: int = 1,
               timeout: float = 0) -> ChromiumElement:
        """返回上面某一级父元素,可指定层数或用查询语法定位
        :param level_or_loc: 第几级父元素,1开始,或定位符
        :param index: 当level_or_loc传入定位符,使用此参数选择第几个结果,1开始
        :param timeout: 查找超时时间(秒)
        :return: 上级元素对象
        """
        ...

    def child(self,
              locator: Union[Tuple[str, str], str, int] = '',
              index: int = 1,
              timeout: float = None,
              ele_only: bool = True) -> Union[ChromiumElement, str]:
        """返回当前元素的一个符合条件的直接子元素,可用查询语法筛选,可指定返回筛选结果的第几个
        :param locator: 用于筛选的查询语法
        :param index: 第几个查询结果,1开始
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 直接子元素或节点文本
        """
        ...

    def prev(self,
             locator: Union[Tuple[str, str], str, int] = '',
             index: int = 1,
             timeout: float = None,
             ele_only: bool = True) -> Union[ChromiumElement, str]:
        """返回当前元素前面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个
        :param locator: 用于筛选的查询语法
        :param index: 前面第几个查询结果,1开始
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 兄弟元素或节点文本
        """
        ...

    def next(self,
             locator: Union[Tuple[str, str], str, int] = '',
             index: int = 1,
             timeout: float = None,
             ele_only: bool = True) -> Union[ChromiumElement, str]:
        """返回当前元素后面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个
        :param locator: 用于筛选的查询语法
        :param index: 第几个查询结果,1开始
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 兄弟元素或节点文本
        """
        ...

    def before(self,
               locator: Union[Tuple[str, str], str, int] = '',
               index: int = 1,
               timeout: float = None,
               ele_only: bool = True) -> Union[ChromiumElement, str]:
        """返回文档中当前元素前面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个
        查找范围不限同级元素,而是整个DOM文档
        :param locator: 用于筛选的查询语法
        :param index: 前面第几个查询结果,1开始
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 本元素前面的某个元素或节点
        """
        ...

    def after(self,
              locator: Union[Tuple[str, str], str, int] = '',
              index: int = 1,
              timeout: float = None,
              ele_only: bool = True) -> Union[ChromiumElement, str]:
        """返回文档中此当前元素后面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个
        查找范围不限同级元素,而是整个DOM文档
        :param locator: 用于筛选的查询语法
        :param index: 第几个查询结果,1开始
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 本元素后面的某个元素或节点
        """
        ...

    def children(self,
                 locator: Union[Tuple[str, str], str] = '',
                 timeout: float = None,
                 ele_only: bool = True) -> Union[ChromiumElementsList, List[Union[ChromiumElement, str]]]:
        """返回当前元素符合条件的直接子元素或节点组成的列表,可用查询语法筛选
        :param locator: 用于筛选的查询语法
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 直接子元素或节点文本组成的列表
        """
        ...

    def prevs(self,
              locator: Union[Tuple[str, str], str] = '',
              timeout: float = None,
              ele_only: bool = True) -> Union[ChromiumElementsList, List[Union[ChromiumElement, str]]]:
        """返回当前元素前面符合条件的同级元素或节点组成的列表,可用查询语法筛选
        :param locator: 用于筛选的查询语法
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 兄弟元素或节点文本组成的列表
        """
        ...

    def nexts(self,
              locator: Union[Tuple[str, str], str] = '',
              timeout: float = None,
              ele_only: bool = True) -> Union[ChromiumElementsList, List[Union[ChromiumElement, str]]]:
        """返回当前元素后面符合条件的同级元素或节点组成的列表,可用查询语法筛选
        :param locator: 用于筛选的查询语法
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 兄弟元素或节点文本组成的列表
        """
        ...

    def befores(self,
                locator: Union[Tuple[str, str], str] = '',
                timeout: float = None,
                ele_only: bool = True) -> Union[ChromiumElementsList, List[Union[ChromiumElement, str]]]:
        """返回文档中当前元素前面符合条件的元素或节点组成的列表,可用查询语法筛选
        查找范围不限同级元素,而是整个DOM文档
        :param locator: 用于筛选的查询语法
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 本元素前面的元素或节点组成的列表
        """
        ...

    def afters(self,
               locator: Union[Tuple[str, str], str] = '',
               timeout: float = None,
               ele_only: bool = True) -> Union[ChromiumElementsList, List[Union[ChromiumElement, str]]]:
        """返回文档中当前元素后面符合条件的元素或节点组成的列表,可用查询语法筛选
        查找范围不限同级元素,而是整个DOM文档
        :param locator: 用于筛选的查询语法
        :param timeout: 查找节点的超时时间(秒)
        :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入
        :return: 本元素后面的元素或节点组成的列表
        """
        ...

    def over(self, timeout: float = None) -> ChromiumElement:
        """获取覆盖在本元素上最上层的元素
        :param timeout: 等待元素出现的超时时间(秒)
        :return: 元素对象
        """
        ...

    def offset(self,
               locator: Optional[str] = None,
               x: int = None,
               y: int = None,
               timeout: float = None) -> ChromiumElement:
        """获取相对本元素左上角左边指定偏移量位置的元素,如果offset_x和offset_y都是None,定位到元素中间点
        :param locator: 定位符,只支持str,且不支持xpath和css方式
        :param x: 横坐标偏移量,向右为正
        :param y: 纵坐标偏移量,向下为正
        :param timeout: 超时时间(秒),为None使用所在页面设置
        :return: 元素对象
        """
        ...

    def east(self, loc_or_pixel: Union[str, int, None] = None, index: int = 1) -> ChromiumElement:
        """获取元素右边某个指定元素
        :param loc_or_pixel: 定位符,只支持str或int,且不支持xpath和css方式,传入int按像素距离获取
        :param index: 第几个,从1开始
        :return: 获取到的元素对象
        """
        ...

    def south(self, loc_or_pixel: Union[str, int, None] = None, index: int = 1) -> ChromiumElement:
        """获取元素下方某个指定元素
        :param loc_or_pixel: 定位符,只支持str或int,且不支持xpath和css方式,传入int按像素距离获取
        :param index: 第几个,从1开始
        :return: 获取到的元素对象
        """
        ...

    def west(self, loc_or_pixel: Union[str, int, None] = None, index: int = 1) -> ChromiumElement:
        """获取元素左边某个指定元素
        :param loc_or_pixel: 定位符,只支持str或int,且不支持xpath和css方式,传入int按像素距离获取
        :param index: 第几个,从1开始
        :return: 获取到的元素对象
        """
        ...

    def north(self, loc_or_pixel: Union[str, int, None] = None, index: int = 1) -> ChromiumElement:
        """获取元素上方某个指定元素
        :param loc_or_pixel: 定位符,只支持str或int,且不支持xpath和css方式,传入int按像素距离获取
        :param index: 第几个,从1开始
        :return: 获取到的元素对象
        """
        ...

    def _get_relative_eles(self,
                           mode: str = 'north',
                           locator: Union[int, str] = None,
                           index: int = 1) -> ChromiumElement:
        """获取元素下方某个指定元素
        :param locator: 定位符,只支持str或int,且不支持xpath和css方式
        :param index: 第几个,从1开始
        :return: 获取到的元素对象
        """
        ...

    def check(self, uncheck: bool = False, by_js: bool = False) -> None:
        """选中或取消选中当前元素
        :param uncheck: 是否取消选中
        :param by_js: 是否用js执行
        :return: None
        """
        ...

    def attr(self, name: str) -> Union[str, None]:
        """返回一个attribute属性值
        :param name: 属性名
        :return: 属性值文本,没有该属性返回None
        """
        ...

    def remove_attr(self, name: str) -> ChromiumElement:
        """删除元素一个attribute属性
        :param name: 属性名
        :return: None
        """
        ...

    def property(self, name: str) -> Union[str, int, None]:
        """获取一个property属性值
        :param name: 属性名
        :return: 属性值文本
        """
        ...

    def run_js(self, script: str, *args, as_expr: bool = False, timeout: float = None) -> Any:
        """对本元素执行javascript代码
        :param script: js文本,文本中用this表示本元素
        :param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
        :param as_expr: 是否作为表达式运行,为True时args无效
        :param timeout: js超时时间(秒),为None则使用页面timeouts.script设置
        :return: 运行的结果
        """
        ...

    def _run_js(self, script: str, *args, as_expr: bool = False, timeout: float = None) -> Any:
        """对本元素执行javascript代码
        :param script: js文本,文本中用this表示本元素
        :param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
        :param as_expr: 是否作为表达式运行,为True时args无效
        :param timeout: js超时时间(秒),为None则使用页面timeouts.script设置
        :return: 运行的结果
        """
        ...

    def run_async_js(self, script: str, *args, as_expr: bool = False) -> None:
        """以异步方式对本元素执行javascript代码
        :param script: js文本,文本中用this表示本元素
        :param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
        :param as_expr: 是否作为表达式运行,为True时args无效
        :return: None
        """
        ...

    def ele(self,
            locator: Union[Tuple[str, str], str],
            index: int = 1,
            timeout: float = None) -> ChromiumElement:
        """返回当前元素下级符合条件的一个元素、属性或节点文本
        :param locator: 元素的定位信息,可以是loc元组,或查询字符串
        :param index: 获取第几个元素,从1开始,可传入负数获取倒数第几个
        :param timeout: 查找元素超时时间(秒),默认与元素所在页面等待时间一致
        :return: ChromiumElement对象或属性、文本
        """
        ...

    def eles(self,
             locator: Union[Tuple[str, str], str],
             timeout: float = None) -> ChromiumElementsList:
        """返回当前元素下级所有符合条件的子元素、属性或节点文本
        :param locator: 元素的定位信息,可以是loc元组,或查询字符串
        :param timeout: 查找元素超时时间(秒),默认与元素所在页面等待时间一致
        :return: ChromiumElement对象或属性、文本组成的列表
        """
        ...

    def s_ele(self,
              locator: Union[Tuple[str, str], str] = None,
              index: int = 1,
              timeout: float = None) -> SessionElement:
        """查找一个符合条件的元素,以SessionElement形式返回
        :param locator: 元素的定位信息,可以是loc元组,或查询字符串
        :param index: 获取第几个,从1开始,可传入负数获取倒数第几个
        :param timeout: 查找元素超时时间(秒),默认与元素所在页面等待时间一致
        :return: SessionElement对象或属性、文本
        """
        ...

    def s_eles(self,
               locator: Union[Tuple[str, str], str] = None,
               timeout: float = None) -> SessionElementsList:
        """查找所有符合条件的元素,以SessionElement列表形式返回
        :param locator: 定位符
        :param timeout: 查找元素超时时间(秒),默认与元素所在页面等待时间一致
        :return: SessionElement或属性、文本组成的列表
        """
        ...

    def _find_elements(self,
                       locator: Union[Tuple[str, str], str],
                       timeout: float,
                       index: Optional[int] = 1,
                       relative: bool = False,
                       raise_err: bool = False) -> Union[ChromiumElement, ChromiumFrame, ChromiumElementsList]:
        """返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个
        :param locator: 元素的定位信息,可以是loc元组,或查询字符串
        :param timeout: 查找元素超时时间(秒)
        :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有
        :param relative: MixTab用的表示是否相对定位的参数
        :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置
        :return: ChromiumElement对象或文本、属性或其组成的列表
        """
        ...

    def style(self, style: str, pseudo_ele: str = '') -> str:
        """返回元素样式属性值,可获取伪元素属性值
        :param style: 样式属性名称
        :param pseudo_ele: 伪元素名称(如有)
        :return: 样式属性的值
        """
        ...

    def src(self, timeout: float = None, base64_to_bytes: bool = True) -> Union[bytes, str, None]:
        """返回元素src资源,base64的可转为bytes返回,其它返回str
        :param timeout: 等待资源加载的超时时间(秒)
        :param base64_to_bytes: 为True时,如果是base64数据,转换为bytes格式
        :return: 资源内容
        """
        ...

    def save(self,
             path: [str, bool] = None,
             name: str = None,
             timeout: float = None,
             rename: bool = True) -> str:
        """保存图片或其它有src属性的元素的资源
        :param path: 文件保存路径,为None时保存到当前文件夹
        :param name: 文件名称,为None时从资源url获取
        :param timeout: 等待资源加载的超时时间(秒)
        :param rename: 遇到重名文件时是否自动重命名
        :return: 返回保存路径
        """
        ...

    def get_screenshot(self,
                       path: [str, Path] = None,
                       name: str = None,
                       as_bytes: PIC_TYPE = None,
                       as_base64: PIC_TYPE = None,
                       scroll_to_center: bool = True) -> Union[str, bytes]:
        """对当前元素截图,可保存到文件,或以字节方式返回
        :par
Download .txt
gitextract_pk4tkf1v/

├── .github/
│   └── FUNDING.yml
├── .gitignore
├── DrissionPage/
│   ├── __init__.py
│   ├── __init__.pyi
│   ├── _base/
│   │   ├── base.py
│   │   ├── base.pyi
│   │   ├── chromium.py
│   │   ├── chromium.pyi
│   │   ├── driver.py
│   │   └── driver.pyi
│   ├── _configs/
│   │   ├── chromium_options.py
│   │   ├── chromium_options.pyi
│   │   ├── configs.ini
│   │   ├── options_manage.py
│   │   ├── options_manage.pyi
│   │   ├── session_options.py
│   │   └── session_options.pyi
│   ├── _elements/
│   │   ├── chromium_element.py
│   │   ├── chromium_element.pyi
│   │   ├── none_element.py
│   │   ├── none_element.pyi
│   │   ├── session_element.py
│   │   └── session_element.pyi
│   ├── _functions/
│   │   ├── browser.py
│   │   ├── browser.pyi
│   │   ├── by.py
│   │   ├── cli.py
│   │   ├── cookies.py
│   │   ├── cookies.pyi
│   │   ├── elements.py
│   │   ├── elements.pyi
│   │   ├── keys.py
│   │   ├── keys.pyi
│   │   ├── locator.py
│   │   ├── locator.pyi
│   │   ├── settings.py
│   │   ├── settings.pyi
│   │   ├── texts.py
│   │   ├── tools.py
│   │   ├── tools.pyi
│   │   ├── web.py
│   │   └── web.pyi
│   ├── _pages/
│   │   ├── chromium_base.py
│   │   ├── chromium_base.pyi
│   │   ├── chromium_frame.py
│   │   ├── chromium_frame.pyi
│   │   ├── chromium_page.py
│   │   ├── chromium_page.pyi
│   │   ├── chromium_tab.py
│   │   ├── chromium_tab.pyi
│   │   ├── mix_tab.py
│   │   ├── mix_tab.pyi
│   │   ├── session_page.py
│   │   ├── session_page.pyi
│   │   ├── web_page.py
│   │   └── web_page.pyi
│   ├── _units/
│   │   ├── actions.py
│   │   ├── actions.pyi
│   │   ├── clicker.py
│   │   ├── clicker.pyi
│   │   ├── console.py
│   │   ├── console.pyi
│   │   ├── cookies_setter.py
│   │   ├── cookies_setter.pyi
│   │   ├── downloader.py
│   │   ├── downloader.pyi
│   │   ├── listener.py
│   │   ├── listener.pyi
│   │   ├── rect.py
│   │   ├── rect.pyi
│   │   ├── screencast.py
│   │   ├── screencast.pyi
│   │   ├── scroller.py
│   │   ├── scroller.pyi
│   │   ├── selector.py
│   │   ├── selector.pyi
│   │   ├── setter.py
│   │   ├── setter.pyi
│   │   ├── states.py
│   │   ├── states.pyi
│   │   ├── waiter.py
│   │   └── waiter.pyi
│   ├── common.py
│   ├── errors.py
│   ├── items.py
│   └── version.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── docs_en/
│   ├── .nojekyll
│   ├── ChromiumPage/
│   │   ├── actions.md
│   │   ├── browser_options.md
│   │   ├── create_page_object.md
│   │   ├── element_operation.md
│   │   ├── frame_operation.md
│   │   ├── get_element_info.md
│   │   ├── get_elements.md
│   │   ├── get_page_info.md
│   │   ├── introduction.md
│   │   ├── network_listener.md
│   │   ├── page_operation.md
│   │   ├── screen_recording.md
│   │   ├── tab_operation.md
│   │   ├── upload_files.md
│   │   ├── visit_web_page.md
│   │   └── waiting.md
│   ├── MixPage/
│   │   └── introduction.md
│   ├── Q&A.md
│   ├── README_en.md
│   ├── SessionPage/
│   │   ├── create_page_object.md
│   │   ├── get_element_info.md
│   │   ├── get_elements.md
│   │   ├── get_page_info.md
│   │   ├── introduction.md
│   │   ├── session_options.md
│   │   ├── set_session.md
│   │   └── visit_web_page.md
│   ├── WebPage/
│   │   ├── create_page_object.md
│   │   ├── introduction.md
│   │   ├── mode_switch.md
│   │   └── webpage_function.md
│   ├── advance/
│   │   ├── accelerate_reading.md
│   │   ├── commands.md
│   │   ├── errors.md
│   │   ├── ini_file.md
│   │   ├── packaging.md
│   │   ├── settings.md
│   │   └── tools.md
│   ├── cooperation.md
│   ├── demos/
│   │   ├── douban_book_pics.md
│   │   ├── login_gitee.md
│   │   ├── maoyan_TOP100.md
│   │   ├── multithreading_with_tabs.md
│   │   └── starbucks_pics.md
│   ├── download/
│   │   ├── DownloadKit.md
│   │   ├── browser.md
│   │   └── introduction.md
│   ├── features/
│   │   ├── features_demos/
│   │   │   ├── compare_with_requests.md
│   │   │   ├── compare_with_selenium.md
│   │   │   ├── download_file.md
│   │   │   ├── get_element_attributes.md
│   │   │   └── switch_mode.md
│   │   └── intimate_design.md
│   ├── get_elements/
│   │   ├── cheat_sheet.md
│   │   ├── introduction.md
│   │   ├── more.md
│   │   ├── not_found.md
│   │   ├── simplify.md
│   │   └── usage.md
│   ├── get_start/
│   │   ├── basic_concept.md
│   │   ├── before_start.md
│   │   ├── examples/
│   │   │   ├── control_browser.md
│   │   │   ├── data_packets.md
│   │   │   └── switch_mode.md
│   │   ├── import.md
│   │   └── installation.md
│   ├── history/
│   │   ├── 1.x.md
│   │   ├── 2.x.md
│   │   ├── 3.x.md
│   │   ├── 4.x.md
│   │   └── statement.md
│   ├── usage_introduction.md
│   └── whatsnew/
│       ├── 3_2.md
│       └── 4_0.md
├── requirements.txt
└── setup.py
Download .txt
SYMBOL INDEX (2576 symbols across 79 files)

FILE: DrissionPage/_base/base.py
  class BaseParser (line 26) | class BaseParser(object):
    method __call__ (line 27) | def __call__(self, locator):
    method ele (line 30) | def ele(self, locator, index=1, timeout=None):
    method eles (line 33) | def eles(self, locator, timeout=None):
    method find (line 36) | def find(self, locators, any_one=True, first_ele=True, timeout=None):
    method html (line 51) | def html(self):
    method s_ele (line 54) | def s_ele(self, locator=None):
    method s_eles (line 57) | def s_eles(self, locator):
    method _ele (line 60) | def _ele(self, locator, timeout=None, index=1, raise_err=None, method=...
    method _find_elements (line 63) | def _find_elements(self, locator, timeout, index=1, relative=False, ra...
  class BaseElement (line 67) | class BaseElement(BaseParser):
    method __init__ (line 68) | def __init__(self, owner=None):
    method get_frame (line 72) | def get_frame(self, loc_or_ind, timeout=None):
    method _ele (line 78) | def _ele(self, locator, timeout=None, index=1, relative=False, raise_e...
    method timeout (line 94) | def timeout(self):
    method child_count (line 98) | def child_count(self):
    method tag (line 103) | def tag(self):
    method parent (line 106) | def parent(self, level_or_loc=1):
    method next (line 109) | def next(self, index=1):
    method nexts (line 112) | def nexts(self):
  class DrissionElement (line 116) | class DrissionElement(BaseElement):
    method link (line 119) | def link(self):
    method css_path (line 123) | def css_path(self):
    method xpath (line 127) | def xpath(self):
    method comments (line 131) | def comments(self):
    method texts (line 134) | def texts(self, text_node_only=False):
    method parent (line 139) | def parent(self, level_or_loc=1, index=1, timeout=None):
    method child (line 155) | def child(self, locator='', index=1, timeout=None, ele_only=True):
    method prev (line 171) | def prev(self, locator='', index=1, timeout=None, ele_only=True):
    method next (line 174) | def next(self, locator='', index=1, timeout=None, ele_only=True):
    method before (line 177) | def before(self, locator='', index=1, timeout=None, ele_only=True):
    method after (line 180) | def after(self, locator='', index=1, timeout=None, ele_only=True):
    method children (line 183) | def children(self, locator='', timeout=None, ele_only=True):
    method prevs (line 196) | def prevs(self, locator='', timeout=None, ele_only=True):
    method nexts (line 199) | def nexts(self, locator='', timeout=None, ele_only=True):
    method befores (line 202) | def befores(self, locator='', timeout=None, ele_only=True):
    method afters (line 206) | def afters(self, locator='', timeout=None, ele_only=True):
    method _get_relative (line 210) | def _get_relative(self, func, direction, brother, locator='', index=1,...
    method _get_relatives (line 218) | def _get_relatives(self, index=None, locator='', direction='following'...
    method attrs (line 241) | def attrs(self):
    method text (line 245) | def text(self):
    method raw_text (line 249) | def raw_text(self):
    method attr (line 253) | def attr(self, name):
    method _get_ele_path (line 256) | def _get_ele_path(self, xpath=True):
    method _find_elements (line 259) | def _find_elements(self, locator, timeout, index=1, relative=False, ra...
  class BasePage (line 263) | class BasePage(BaseParser):
    method __init__ (line 265) | def __init__(self):
    method title (line 280) | def title(self):
    method url_available (line 285) | def url_available(self):
    method download_path (line 289) | def download_path(self):
    method download (line 293) | def download(self):
    method _before_connect (line 300) | def _before_connect(self, url, retry, interval):
    method _set_session_options (line 313) | def _set_session_options(self, session_or_options=None):
    method _create_session (line 326) | def _create_session(self):
    method url (line 333) | def url(self):
    method json (line 337) | def json(self):
    method user_agent (line 341) | def user_agent(self):
    method get (line 345) | def get(self, url, show_errmsg=False, retry=None, interval=None):
    method _ele (line 348) | def _ele(self, locator, timeout=None, index=1, raise_err=None, method=...

FILE: DrissionPage/_base/base.pyi
  class BaseParser (line 26) | class BaseParser(object):
    method __call__ (line 31) | def __call__(self, locator: Union[Tuple[str, str], str], index: int = ...
    method ele (line 33) | def ele(self,
    method eles (line 38) | def eles(self, locator: Union[Tuple[str, str], str], timeout=None): ...
    method find (line 40) | def find(self,
    method html (line 59) | def html(self) -> str: ...
    method s_ele (line 61) | def s_ele(self,
    method s_eles (line 65) | def s_eles(self, locator: Union[Tuple[str, str], str]) -> SessionEleme...
    method _ele (line 67) | def _ele(self,
    method _find_elements (line 74) | def _find_elements(self,
  class BaseElement (line 82) | class BaseElement(BaseParser):
    method __init__ (line 86) | def __init__(self, owner: BasePage = None): ...
    method timeout (line 89) | def timeout(self) -> float:
    method child_count (line 94) | def child_count(self) -> int:
    method tag (line 100) | def tag(self) -> str: ...
    method parent (line 102) | def parent(self, level_or_loc: Union[tuple, str, int] = 1): ...
    method prev (line 104) | def prev(self, index: int = 1) -> None: ...
    method prevs (line 106) | def prevs(self) -> None: ...
    method next (line 108) | def next(self, index: int = 1): ...
    method nexts (line 110) | def nexts(self): ...
    method get_frame (line 112) | def get_frame(self, loc_or_ind, timeout=None) -> ChromiumFrame:
    method _ele (line 120) | def _ele(self,
  class DrissionElement (line 139) | class DrissionElement(BaseElement):
    method __init__ (line 142) | def __init__(self, owner: BasePage = None): ...
    method link (line 145) | def link(self) -> str:
    method css_path (line 150) | def css_path(self) -> str:
    method xpath (line 155) | def xpath(self) -> str:
    method comments (line 160) | def comments(self) -> list:
    method texts (line 164) | def texts(self, text_node_only: bool = False) -> list:
    method parent (line 171) | def parent(self,
    method child (line 183) | def child(self,
    method prev (line 197) | def prev(self,
    method next (line 211) | def next(self,
    method before (line 225) | def before(self,
    method after (line 239) | def after(self,
    method children (line 253) | def children(self,
    method prevs (line 265) | def prevs(self,
    method nexts (line 277) | def nexts(self,
    method befores (line 289) | def befores(self,
    method afters (line 301) | def afters(self,
    method _get_relative (line 313) | def _get_relative(self,
    method _get_relatives (line 332) | def _get_relatives(self,
    method attrs (line 351) | def attrs(self) -> dict: ...
    method text (line 354) | def text(self) -> str: ...
    method raw_text (line 357) | def raw_text(self) -> str: ...
    method attr (line 360) | def attr(self, name: str) -> str: ...
    method _get_ele_path (line 362) | def _get_ele_path(self, xpath: bool = True) -> str: ...
  class BasePage (line 365) | class BasePage(BaseParser):
    method __init__ (line 380) | def __init__(self): ...
    method title (line 383) | def title(self) -> Union[str, None]:
    method url_available (line 388) | def url_available(self) -> bool:
    method download_path (line 393) | def download_path(self) -> str:
    method download (line 398) | def download(self) -> DrissionGet:
    method _before_connect (line 402) | def _before_connect(self, url: str, retry: int, interval: float) -> tu...
    method _set_session_options (line 411) | def _set_session_options(self, session_or_options: Union[Session, Sess...
    method _create_session (line 418) | def _create_session(self) -> None:
    method url (line 424) | def url(self) -> str: ...
    method json (line 427) | def json(self) -> dict: ...
    method user_agent (line 430) | def user_agent(self) -> str: ...
    method get (line 433) | def get(self, url: str, show_errmsg: bool = False, retry: int = None, ...
    method _ele (line 435) | def _ele(self,

FILE: DrissionPage/_base/chromium.py
  class Chromium (line 35) | class Chromium(object):
    method __new__ (line 39) | def __new__(cls, addr_or_opts=None, session_options=None):
    method __init__ (line 57) | def __init__(self, addr_or_opts=None, session_options=None):
    method user_data_path (line 123) | def user_data_path(self):
    method process_id (line 127) | def process_id(self):
    method timeout (line 131) | def timeout(self):
    method timeouts (line 135) | def timeouts(self):
    method load_mode (line 139) | def load_mode(self):
    method download_path (line 143) | def download_path(self):
    method set (line 147) | def set(self):
    method states (line 153) | def states(self):
    method wait (line 159) | def wait(self):
    method tabs_count (line 165) | def tabs_count(self):
    method tab_ids (line 170) | def tab_ids(self):
    method latest_tab (line 179) | def latest_tab(self):
    method cookies (line 182) | def cookies(self, all_info=False):
    method new_tab (line 187) | def new_tab(self, url=None, new_window=False, background=False, new_co...
    method get_tab (line 190) | def get_tab(self, id_or_num=None, title=None, url=None, tab_type='page'):
    method get_tabs (line 196) | def get_tabs(self, title=None, url=None, tab_type='page'):
    method close_tabs (line 199) | def close_tabs(self, tabs_or_ids, others=False):
    method _close_tab (line 220) | def _close_tab(self, tab):
    method activate_tab (line 227) | def activate_tab(self, id_ind_tab):
    method reconnect (line 235) | def reconnect(self):
    method clear_cache (line 245) | def clear_cache(self, cache=True, cookies=True):
    method quit (line 252) | def quit(self, timeout=5, force=False, del_data=False):
    method _new_tab (line 304) | def _new_tab(self, mix=True, url=None, new_window=False, background=Fa...
    method _get_tab (line 337) | def _get_tab(self, id_or_num=None, title=None, url=None, tab_type='pag...
    method _get_tabs (line 365) | def _get_tabs(self, title=None, url=None, tab_type='page', mix=True, a...
    method _run_cdp (line 392) | def _run_cdp(self, cmd, **cmd_args):
    method _get_driver (line 397) | def _get_driver(self, tab_id, owner=None):
    method _onTargetCreated (line 409) | def _onTargetCreated(self, **kwargs):
    method _onTargetDestroyed (line 428) | def _onTargetDestroyed(self, **kwargs):
    method _on_disconnect (line 439) | def _on_disconnect(self):
  function handle_options (line 456) | def handle_options(addr_or_opts):
  function run_browser (line 486) | def run_browser(chromium_options):
  function _new_tab_by_js (line 544) | def _new_tab_by_js(browser: Chromium, url, tab_type, new_window):

FILE: DrissionPage/_base/chromium.pyi
  class Chromium (line 24) | class Chromium(object):
    method __new__ (line 59) | def __new__(cls,
    method __init__ (line 68) | def __init__(self, addr_or_opts: Union[str, int, ChromiumOptions] = None,
    method user_data_path (line 77) | def user_data_path(self) -> str:
    method process_id (line 82) | def process_id(self) -> Optional[int]:
    method timeout (line 87) | def timeout(self) -> float:
    method timeouts (line 92) | def timeouts(self) -> Timeout:
    method load_mode (line 97) | def load_mode(self) -> Literal['none', 'normal', 'eager']:
    method download_path (line 102) | def download_path(self) -> str:
    method set (line 107) | def set(self) -> BrowserSetter:
    method states (line 112) | def states(self) -> BrowserStates:
    method wait (line 117) | def wait(self) -> BrowserWaiter:
    method tabs_count (line 122) | def tabs_count(self) -> int:
    method tab_ids (line 127) | def tab_ids(self) -> List[str]:
    method latest_tab (line 132) | def latest_tab(self) -> Union[MixTab, str]:
    method cookies (line 137) | def cookies(self, all_info: bool = False) -> CookiesList:
    method new_tab (line 144) | def new_tab(self,
    method get_tab (line 158) | def get_tab(self,
    method get_tabs (line 174) | def get_tabs(self,
    method close_tabs (line 188) | def close_tabs(self,
    method _close_tab (line 199) | def _close_tab(self, tab: Union[ChromiumBase, str]):
    method activate_tab (line 205) | def activate_tab(self, id_ind_tab: Union[int, str, ChromiumTab]) -> None:
    method reconnect (line 212) | def reconnect(self) -> None:
    method clear_cache (line 216) | def clear_cache(self, cache: bool = True, cookies: bool = True) -> None:
    method quit (line 224) | def quit(self, timeout: float = 5, force: bool = False, del_data: bool...
    method _new_tab (line 233) | def _new_tab(self,
    method _get_tab (line 249) | def _get_tab(self,
    method _get_tabs (line 267) | def _get_tabs(self,
    method _run_cdp (line 283) | def _run_cdp(self, cmd, **cmd_args) -> dict:
    method _get_driver (line 291) | def _get_driver(self, tab_id: str, owner=None) -> Driver:
    method _onTargetCreated (line 299) | def _onTargetCreated(self, **kwargs): ...
    method _onTargetDestroyed (line 301) | def _onTargetDestroyed(self, **kwargs): ...
    method _on_disconnect (line 303) | def _on_disconnect(self): ...
  function handle_options (line 306) | def handle_options(addr_or_opts):
  function run_browser (line 314) | def run_browser(chromium_options)->Tuple[bool, str, bool, bool, BrowserD...

FILE: DrissionPage/_base/driver.py
  class Driver (line 24) | class Driver(object):
    method __init__ (line 25) | def __init__(self, _id, address, owner=None):
    method _send (line 51) | def _send(self, message, timeout=None):
    method _recv_loop (line 88) | def _recv_loop(self):
    method _handle_event_loop (line 112) | def _handle_event_loop(self):
    method _handle_immediate_event_loop (line 125) | def _handle_immediate_event_loop(self):
    method _handle_immediate_event (line 133) | def _handle_immediate_event(self, function, kwargs):
    method run (line 140) | def run(self, _method, **kwargs):
    method start (line 156) | def start(self):
    method stop (line 171) | def stop(self):
    method _stop (line 177) | def _stop(self):
    method set_callback (line 193) | def set_callback(self, event, callback, immediate=False):
  class BrowserDriver (line 201) | class BrowserDriver(Driver):
    method __new__ (line 204) | def __new__(cls, _id, address, owner):
    method __init__ (line 209) | def __init__(self, _id, address, owner):
    method __repr__ (line 216) | def __repr__(self):
    method get (line 220) | def get(url):

FILE: DrissionPage/_base/driver.pyi
  class Driver (line 18) | class Driver(object):
    method __init__ (line 36) | def __init__(self, _id: str, address: str, owner=None):
    method _send (line 44) | def _send(self, message: dict, timeout: float = None) -> dict:
    method _recv_loop (line 52) | def _recv_loop(self) -> None:
    method _handle_event_loop (line 56) | def _handle_event_loop(self) -> None:
    method _handle_immediate_event_loop (line 60) | def _handle_immediate_event_loop(self): ...
    method _handle_immediate_event (line 62) | def _handle_immediate_event(self, function: Callable, kwargs: dict):
    method run (line 70) | def run(self, _method: str, **kwargs) -> dict:
    method start (line 78) | def start(self) -> bool:
    method stop (line 82) | def stop(self) -> bool:
    method _stop (line 86) | def _stop(self) -> None:
    method set_callback (line 90) | def set_callback(self, event: str, callback: Union[Callable, None], im...
  class BrowserDriver (line 100) | class BrowserDriver(Driver):
    method __new__ (line 104) | def __new__(cls, _id: str, address: str, owner: Chromium):
    method __init__ (line 112) | def __init__(self, _id: str, address: str, owner: Optional[Chromium]):
    method get (line 121) | def get(url) -> Response:

FILE: DrissionPage/_configs/chromium_options.py
  class ChromiumOptions (line 16) | class ChromiumOptions(object):
    method __init__ (line 17) | def __init__(self, read_file=True, ini_path=None):
    method __repr__ (line 82) | def __repr__(self):
    method download_path (line 86) | def download_path(self):
    method browser_path (line 90) | def browser_path(self):
    method user_data_path (line 94) | def user_data_path(self):
    method tmp_path (line 98) | def tmp_path(self):
    method user (line 102) | def user(self):
    method load_mode (line 106) | def load_mode(self):
    method timeouts (line 110) | def timeouts(self):
    method proxy (line 114) | def proxy(self):
    method address (line 118) | def address(self):
    method arguments (line 122) | def arguments(self):
    method extensions (line 126) | def extensions(self):
    method preferences (line 130) | def preferences(self):
    method flags (line 134) | def flags(self):
    method system_user_path (line 138) | def system_user_path(self):
    method is_existing_only (line 142) | def is_existing_only(self):
    method is_auto_port (line 146) | def is_auto_port(self):
    method retry_times (line 150) | def retry_times(self):
    method retry_interval (line 154) | def retry_interval(self):
    method is_headless (line 158) | def is_headless(self):
    method set_retry (line 161) | def set_retry(self, times=None, interval=None):
    method set_argument (line 168) | def set_argument(self, arg, value=None):
    method remove_argument (line 186) | def remove_argument(self, value):
    method add_extension (line 198) | def add_extension(self, path):
    method remove_extensions (line 202) | def remove_extensions(self):
    method set_pref (line 206) | def set_pref(self, arg, value):
    method remove_pref (line 210) | def remove_pref(self, arg):
    method remove_pref_from_file (line 214) | def remove_pref_from_file(self, arg):
    method set_flag (line 218) | def set_flag(self, flag, value=None):
    method clear_flags_in_file (line 225) | def clear_flags_in_file(self):
    method clear_flags (line 229) | def clear_flags(self):
    method clear_arguments (line 233) | def clear_arguments(self):
    method clear_prefs (line 237) | def clear_prefs(self):
    method set_timeouts (line 241) | def set_timeouts(self, base=None, page_load=None, script=None):
    method set_user (line 251) | def set_user(self, user='Default'):
    method headless (line 256) | def headless(self, on_off=True):
    method no_imgs (line 260) | def no_imgs(self, on_off=True):
    method no_js (line 264) | def no_js(self, on_off=True):
    method mute (line 268) | def mute(self, on_off=True):
    method incognito (line 272) | def incognito(self, on_off=True):
    method new_env (line 277) | def new_env(self, on_off=True):
    method ignore_certificate_errors (line 281) | def ignore_certificate_errors(self, on_off=True):
    method set_user_agent (line 285) | def set_user_agent(self, user_agent):
    method set_proxy (line 288) | def set_proxy(self, proxy):
    method set_load_mode (line 296) | def set_load_mode(self, value):
    method set_paths (line 303) | def set_paths(self, browser_path=None, local_port=None, address=None, ...
    method set_local_port (line 334) | def set_local_port(self, port):
    method set_address (line 340) | def set_address(self, address):
    method set_browser_path (line 352) | def set_browser_path(self, path):
    method set_download_path (line 356) | def set_download_path(self, path):
    method set_tmp_path (line 360) | def set_tmp_path(self, path):
    method set_user_data_path (line 364) | def set_user_data_path(self, path):
    method set_cache_path (line 371) | def set_cache_path(self, path):
    method use_system_user_path (line 375) | def use_system_user_path(self, on_off=True):
    method auto_port (line 379) | def auto_port(self, on_off=True, scope=None):
    method existing_only (line 388) | def existing_only(self, on_off=True):
    method save (line 392) | def save(self, path=None):
    method save_to_default (line 438) | def save_to_default(self):

FILE: DrissionPage/_configs/chromium_options.pyi
  class ChromiumOptions (line 12) | class ChromiumOptions(object):
    method __init__ (line 39) | def __init__(self,
    method download_path (line 49) | def download_path(self) -> str:
    method browser_path (line 54) | def browser_path(self) -> str:
    method user_data_path (line 59) | def user_data_path(self) -> str:
    method tmp_path (line 64) | def tmp_path(self) -> Optional[str]:
    method user (line 69) | def user(self) -> str:
    method load_mode (line 74) | def load_mode(self) -> str:
    method timeouts (line 79) | def timeouts(self) -> dict:
    method proxy (line 84) | def proxy(self) -> str:
    method address (line 89) | def address(self) -> str:
    method arguments (line 94) | def arguments(self) -> list:
    method extensions (line 99) | def extensions(self) -> list:
    method preferences (line 104) | def preferences(self) -> dict:
    method flags (line 109) | def flags(self) -> dict:
    method system_user_path (line 114) | def system_user_path(self) -> bool:
    method is_existing_only (line 119) | def is_existing_only(self) -> bool:
    method is_auto_port (line 124) | def is_auto_port(self) -> Union[bool, Tuple[int, int]]:
    method retry_times (line 129) | def retry_times(self) -> int:
    method retry_interval (line 134) | def retry_interval(self) -> float:
    method is_headless (line 139) | def is_headless(self) -> bool:
    method set_retry (line 143) | def set_retry(self, times: int = None, interval: float = None) -> Chro...
    method set_argument (line 151) | def set_argument(self, arg: str, value: Union[str, None, bool] = None)...
    method remove_argument (line 159) | def remove_argument(self, value: str) -> ChromiumOptions:
    method add_extension (line 166) | def add_extension(self, path: Union[str, Path]) -> ChromiumOptions:
    method remove_extensions (line 173) | def remove_extensions(self) -> ChromiumOptions:
    method set_pref (line 179) | def set_pref(self, arg: str, value: Any) -> ChromiumOptions:
    method remove_pref (line 187) | def remove_pref(self, arg: str) -> ChromiumOptions:
    method remove_pref_from_file (line 194) | def remove_pref_from_file(self, arg: str) -> ChromiumOptions:
    method set_flag (line 201) | def set_flag(self, flag: str, value: Union[int, str, bool] = None) -> ...
    method clear_flags_in_file (line 209) | def clear_flags_in_file(self) -> ChromiumOptions:
    method clear_flags (line 213) | def clear_flags(self) -> ChromiumOptions:
    method clear_arguments (line 217) | def clear_arguments(self) -> ChromiumOptions:
    method clear_prefs (line 221) | def clear_prefs(self) -> ChromiumOptions:
    method set_timeouts (line 225) | def set_timeouts(self,
    method set_user (line 237) | def set_user(self, user: str = 'Default') -> ChromiumOptions:
    method headless (line 244) | def headless(self, on_off: bool = True) -> ChromiumOptions:
    method no_imgs (line 251) | def no_imgs(self, on_off: bool = True) -> ChromiumOptions:
    method no_js (line 258) | def no_js(self, on_off: bool = True) -> ChromiumOptions:
    method mute (line 265) | def mute(self, on_off: bool = True) -> ChromiumOptions:
    method incognito (line 272) | def incognito(self, on_off: bool = True) -> ChromiumOptions:
    method new_env (line 279) | def new_env(self, on_off: bool = True) -> ChromiumOptions:
    method ignore_certificate_errors (line 286) | def ignore_certificate_errors(self, on_off=True) -> ChromiumOptions:
    method set_user_agent (line 293) | def set_user_agent(self, user_agent: str) -> ChromiumOptions:
    method set_proxy (line 300) | def set_proxy(self, proxy: str) -> ChromiumOptions:
    method set_load_mode (line 307) | def set_load_mode(self, value: Literal['normal', 'eager', 'none']) -> ...
    method set_local_port (line 317) | def set_local_port(self, port: Union[str, int]) -> ChromiumOptions:
    method set_address (line 324) | def set_address(self, address: str) -> ChromiumOptions:
    method set_browser_path (line 331) | def set_browser_path(self, path: Union[str, Path]) -> ChromiumOptions:
    method set_download_path (line 338) | def set_download_path(self, path: Union[str, Path]) -> ChromiumOptions:
    method set_tmp_path (line 345) | def set_tmp_path(self, path: Union[str, Path]) -> ChromiumOptions:
    method set_user_data_path (line 352) | def set_user_data_path(self, path: Union[str, Path]) -> ChromiumOptions:
    method set_cache_path (line 359) | def set_cache_path(self, path: Union[str, Path]) -> ChromiumOptions:
    method use_system_user_path (line 366) | def use_system_user_path(self, on_off: bool = True) -> ChromiumOptions:
    method auto_port (line 373) | def auto_port(self,
    method existing_only (line 383) | def existing_only(self, on_off: bool = True) -> ChromiumOptions:
    method save (line 390) | def save(self, path: Union[str, Path] = None) -> str:
    method save_to_default (line 397) | def save_to_default(self) -> str:

FILE: DrissionPage/_configs/options_manage.py
  class OptionsManager (line 15) | class OptionsManager(object):
    method __init__ (line 16) | def __init__(self, path=None):
    method __getattr__ (line 78) | def __getattr__(self, item):
    method get_value (line 81) | def get_value(self, section, item):
    method get_option (line 89) | def get_option(self, section):
    method set_item (line 101) | def set_item(self, section, item, value):
    method remove_item (line 106) | def remove_item(self, section, item):
    method save (line 110) | def save(self, path=None):
    method save_to_default (line 134) | def save_to_default(self):
    method show (line 137) | def show(self):

FILE: DrissionPage/_configs/options_manage.pyi
  class OptionsManager (line 13) | class OptionsManager(object):
    method __init__ (line 19) | def __init__(self, path: Union[Path, str] = None):
    method __getattr__ (line 25) | def __getattr__(self, item) -> dict:
    method get_value (line 32) | def get_value(self, section: str, item: str) -> Any:
    method get_option (line 40) | def get_option(self, section: str) -> dict:
    method set_item (line 47) | def set_item(self, section: str, item: str, value: Any) -> None:
    method remove_item (line 56) | def remove_item(self, section: str, item: str) -> None:
    method save (line 64) | def save(self, path: str = None) -> str:
    method save_to_default (line 71) | def save_to_default(self) -> str:
    method show (line 75) | def show(self) -> None:

FILE: DrissionPage/_configs/session_options.py
  class SessionOptions (line 20) | class SessionOptions(object):
    method __init__ (line 22) | def __init__(self, read_file=True, ini_path=None):
    method __repr__ (line 89) | def __repr__(self):
    method download_path (line 94) | def download_path(self):
    method set_download_path (line 97) | def set_download_path(self, path):
    method timeout (line 102) | def timeout(self):
    method set_timeout (line 105) | def set_timeout(self, second):
    method proxies (line 110) | def proxies(self):
    method set_proxies (line 115) | def set_proxies(self, http=None, https=None):
    method retry_times (line 120) | def retry_times(self):
    method retry_interval (line 124) | def retry_interval(self):
    method set_retry (line 127) | def set_retry(self, times=None, interval=None):
    method headers (line 137) | def headers(self):
    method set_headers (line 142) | def set_headers(self, headers):
    method set_a_header (line 151) | def set_a_header(self, name, value):
    method remove_a_header (line 158) | def remove_a_header(self, name):
    method clear_headers (line 166) | def clear_headers(self):
    method cookies (line 171) | def cookies(self):
    method set_cookies (line 176) | def set_cookies(self, cookies):
    method auth (line 182) | def auth(self):
    method set_auth (line 185) | def set_auth(self, auth):
    method hooks (line 190) | def hooks(self):
    method set_hooks (line 195) | def set_hooks(self, hooks):
    method params (line 200) | def params(self):
    method set_params (line 205) | def set_params(self, params):
    method verify (line 210) | def verify(self):
    method set_verify (line 213) | def set_verify(self, on_off):
    method cert (line 218) | def cert(self):
    method set_cert (line 221) | def set_cert(self, cert):
    method adapters (line 226) | def adapters(self):
    method add_adapter (line 231) | def add_adapter(self, url, adapter):
    method stream (line 236) | def stream(self):
    method set_stream (line 239) | def set_stream(self, on_off):
    method trust_env (line 244) | def trust_env(self):
    method set_trust_env (line 247) | def set_trust_env(self, on_off):
    method max_redirects (line 252) | def max_redirects(self):
    method set_max_redirects (line 255) | def set_max_redirects(self, times):
    method _sets (line 259) | def _sets(self, arg, val):
    method save (line 268) | def save(self, path=None):
    method save_to_default (line 315) | def save_to_default(self):
    method as_dict (line 318) | def as_dict(self):
    method make_session (line 321) | def make_session(self):
    method from_session (line 338) | def from_session(self, session, headers=None):
  function session_options_to_dict (line 355) | def session_options_to_dict(options):

FILE: DrissionPage/_configs/session_options.pyi
  class SessionOptions (line 19) | class SessionOptions(object):
    method __init__ (line 41) | def __init__(self,
    method download_path (line 51) | def download_path(self) -> str:
    method set_download_path (line 55) | def set_download_path(self, path: Union[str, Path]) -> SessionOptions:
    method timeout (line 63) | def timeout(self) -> float:
    method set_timeout (line 67) | def set_timeout(self, second: float) -> SessionOptions:
    method proxies (line 75) | def proxies(self) -> dict:
    method set_proxies (line 79) | def set_proxies(self, http: Union[str, None], https: Union[str, None] ...
    method retry_times (line 88) | def retry_times(self) -> int:
    method retry_interval (line 93) | def retry_interval(self) -> float:
    method set_retry (line 97) | def set_retry(self, times: int = None, interval: float = None) -> Sess...
    method headers (line 106) | def headers(self) -> dict:
    method set_headers (line 110) | def set_headers(self, headers: Union[dict, str, None]) -> SessionOptions:
    method set_a_header (line 117) | def set_a_header(self, name: str, value: str) -> SessionOptions:
    method remove_a_header (line 125) | def remove_a_header(self, name: str) -> SessionOptions:
    method clear_headers (line 132) | def clear_headers(self) -> SessionOptions:
    method cookies (line 137) | def cookies(self) -> list:
    method set_cookies (line 141) | def set_cookies(self, cookies: Union[Cookie, CookieJar, list, tuple, s...
    method auth (line 149) | def auth(self) -> Union[Tuple[str, str], HTTPBasicAuth]:
    method set_auth (line 153) | def set_auth(self, auth: Union[Tuple[str, str], HTTPBasicAuth, None]) ...
    method hooks (line 161) | def hooks(self) -> dict:
    method set_hooks (line 165) | def set_hooks(self, hooks: Union[dict, None]) -> SessionOptions:
    method params (line 173) | def params(self) -> dict:
    method set_params (line 177) | def set_params(self, params: Union[dict, None]) -> SessionOptions:
    method verify (line 185) | def verify(self) -> bool:
    method set_verify (line 189) | def set_verify(self, on_off: Union[bool, None]) -> SessionOptions:
    method cert (line 197) | def cert(self) -> Union[str, tuple]:
    method set_cert (line 201) | def set_cert(self, cert: Union[str, Tuple[str, str], None]) -> Session...
    method adapters (line 209) | def adapters(self) -> list:
    method add_adapter (line 213) | def add_adapter(self, url: str, adapter: HTTPAdapter) -> SessionOptions:
    method stream (line 222) | def stream(self) -> bool:
    method set_stream (line 226) | def set_stream(self, on_off: Union[bool, None]) -> SessionOptions:
    method trust_env (line 234) | def trust_env(self) -> bool:
    method set_trust_env (line 238) | def set_trust_env(self, on_off: Union[bool, None]) -> SessionOptions:
    method max_redirects (line 246) | def max_redirects(self) -> int:
    method set_max_redirects (line 250) | def set_max_redirects(self, times: Union[int, None]) -> SessionOptions:
    method _sets (line 257) | def _sets(self, arg: str, val: Any) -> None:
    method save (line 265) | def save(self, path: str = None) -> str:
    method save_to_default (line 272) | def save_to_default(self) -> str:
    method as_dict (line 276) | def as_dict(self) -> dict:
    method make_session (line 280) | def make_session(self) -> Tuple[Session, Optional[CaseInsensitiveDict]]:
    method from_session (line 284) | def from_session(self, session: Session, headers: CaseInsensitiveDict ...
  function session_options_to_dict (line 293) | def session_options_to_dict(options: Union[dict, SessionOptions, None]) ...

FILE: DrissionPage/_elements/chromium_element.py
  class ChromiumElement (line 38) | class ChromiumElement(DrissionElement):
    method __init__ (line 40) | def __init__(self, owner, node_id=None, obj_id=None, backend_id=None):
    method __call__ (line 74) | def __call__(self, locator, index=1, timeout=None):
    method __repr__ (line 77) | def __repr__(self):
    method __eq__ (line 81) | def __eq__(self, other):
    method tag (line 85) | def tag(self):
    method html (line 92) | def html(self):
    method inner_html (line 96) | def inner_html(self):
    method attrs (line 100) | def attrs(self):
    method text (line 112) | def text(self):
    method raw_text (line 116) | def raw_text(self):
    method set (line 121) | def set(self):
    method states (line 127) | def states(self):
    method pseudo (line 133) | def pseudo(self):
    method rect (line 139) | def rect(self):
    method sr (line 145) | def sr(self):
    method shadow_root (line 154) | def shadow_root(self):
    method scroll (line 158) | def scroll(self):
    method click (line 164) | def click(self):
    method wait (line 170) | def wait(self):
    method select (line 176) | def select(self):
    method value (line 185) | def value(self):
    method check (line 188) | def check(self, uncheck=False, by_js=False):
    method parent (line 206) | def parent(self, level_or_loc=1, index=1, timeout=0):
    method child (line 209) | def child(self, locator='', index=1, timeout=None, ele_only=True):
    method prev (line 212) | def prev(self, locator='', index=1, timeout=None, ele_only=True):
    method next (line 215) | def next(self, locator='', index=1, timeout=None, ele_only=True):
    method before (line 218) | def before(self, locator='', index=1, timeout=None, ele_only=True):
    method after (line 221) | def after(self, locator='', index=1, timeout=None, ele_only=True):
    method children (line 224) | def children(self, locator='', timeout=None, ele_only=True):
    method prevs (line 227) | def prevs(self, locator='', timeout=None, ele_only=True):
    method nexts (line 230) | def nexts(self, locator='', timeout=None, ele_only=True):
    method befores (line 233) | def befores(self, locator='', timeout=None, ele_only=True):
    method afters (line 236) | def afters(self, locator='', timeout=None, ele_only=True):
    method over (line 239) | def over(self, timeout=None):
    method offset (line 249) | def offset(self, locator=None, x=None, y=None, timeout=None):
    method east (line 294) | def east(self, loc_or_pixel=None, index=1):
    method south (line 297) | def south(self, loc_or_pixel=None, index=1):
    method west (line 300) | def west(self, loc_or_pixel=None, index=1):
    method north (line 303) | def north(self, loc_or_pixel=None, index=1):
    method _get_relative_eles (line 306) | def _get_relative_eles(self, mode='north', locator=None, index=1):
    method attr (line 372) | def attr(self, name):
    method remove_attr (line 399) | def remove_attr(self, name):
    method property (line 403) | def property(self, name):
    method run_js (line 410) | def run_js(self, script, *args, as_expr=False, timeout=None):
    method _run_js (line 413) | def _run_js(self, script, *args, as_expr=False, timeout=None):
    method run_async_js (line 416) | def run_async_js(self, script, *args, as_expr=False):
    method ele (line 419) | def ele(self, locator, index=1, timeout=None):
    method eles (line 422) | def eles(self, locator, timeout=None):
    method s_ele (line 425) | def s_ele(self, locator=None, index=1, timeout=None):
    method s_eles (line 430) | def s_eles(self, locator=None, timeout=None):
    method _find_elements (line 434) | def _find_elements(self, locator, timeout, index=1, relative=False, ra...
    method style (line 437) | def style(self, style, pseudo_ele=''):
    method src (line 442) | def src(self, timeout=None, base64_to_bytes=True):
    method save (line 502) | def save(self, path=None, name=None, timeout=None, rename=True):
    method get_screenshot (line 527) | def get_screenshot(self, path=None, name=None, as_bytes=None, as_base6...
    method input (line 547) | def input(self, vals, clear=False, by_js=False):
    method clear (line 574) | def clear(self, by_js=False):
    method _input_focus (line 584) | def _input_focus(self):
    method focus (line 590) | def focus(self):
    method hover (line 597) | def hover(self, offset_x=None, offset_y=None):
    method drag (line 601) | def drag(self, offset_x=0, offset_y=0, duration=.5):
    method drag_to (line 608) | def drag_to(self, ele_or_loc, duration=.5):
    method _get_obj_id (line 617) | def _get_obj_id(self, node_id=None, backend_id=None):
    method _get_node_id (line 623) | def _get_node_id(self, obj_id=None, backend_id=None):
    method _get_backend_id (line 631) | def _get_backend_id(self, node_id):
    method _refresh_id (line 636) | def _refresh_id(self):
    method _get_ele_path (line 640) | def _get_ele_path(self, xpath=True):
    method _set_file_input (line 678) | def _set_file_input(self, files):
  class ShadowRoot (line 686) | class ShadowRoot(BaseElement):
    method __init__ (line 688) | def __init__(self, parent_ele, obj_id=None, backend_id=None):
    method __call__ (line 703) | def __call__(self, locator, index=1, timeout=None):
    method __repr__ (line 706) | def __repr__(self):
    method __eq__ (line 709) | def __eq__(self, other):
    method tag (line 713) | def tag(self):
    method html (line 717) | def html(self):
    method inner_html (line 721) | def inner_html(self):
    method states (line 725) | def states(self):
    method run_js (line 730) | def run_js(self, script, *args, as_expr=False, timeout=None):
    method _run_js (line 733) | def _run_js(self, script, *args, as_expr=False, timeout=None):
    method run_async_js (line 736) | def run_async_js(self, script, *args, as_expr=False, timeout=None):
    method parent (line 741) | def parent(self, level_or_loc=1, index=1, timeout=0):
    method child (line 759) | def child(self, locator='', index=1, timeout=None):
    method next (line 774) | def next(self, locator='', index=1, timeout=None):
    method before (line 786) | def before(self, locator='', index=1, timeout=None):
    method after (line 798) | def after(self, locator='', index=1, timeout=None):
    method children (line 803) | def children(self, locator='', timeout=None):
    method nexts (line 815) | def nexts(self, locator='', timeout=None):
    method befores (line 824) | def befores(self, locator='', timeout=None):
    method afters (line 833) | def afters(self, locator='', timeout=None):
    method ele (line 839) | def ele(self, locator, index=1, timeout=None):
    method eles (line 842) | def eles(self, locator, timeout=None):
    method s_ele (line 845) | def s_ele(self, locator=None, index=1, timeout=None):
    method s_eles (line 850) | def s_eles(self, locator, timeout=None):
    method _find_elements (line 854) | def _find_elements(self, locator, timeout, index=1, relative=False, ra...
    method _get_node_id (line 934) | def _get_node_id(self, obj_id):
    method _get_obj_id (line 937) | def _get_obj_id(self, back_id):
    method _get_backend_id (line 940) | def _get_backend_id(self, node_id):
  function find_in_chromium_ele (line 946) | def find_in_chromium_ele(ele, locator, index=1, timeout=None, relative=T...
  function find_by_xpath (line 971) | def find_by_xpath(ele, xpath, index, timeout, relative=True):
  function find_by_css (line 1036) | def find_by_css(ele, selector, index, timeout):
  function make_chromium_eles (line 1078) | def make_chromium_eles(page, _ids, index=1, is_obj_id=True, ele_only=Fal...
  function _get_node_info (line 1111) | def _get_node_info(page, id_type, _id):
  function _get_node_by_obj_id (line 1121) | def _get_node_by_obj_id(page, obj_id, ele_only):
  function _get_node_by_node_id (line 1132) | def _get_node_by_node_id(page, node_id, ele_only):
  function _make_ele (line 1147) | def _make_ele(page, obj_id, node):
  function make_js_for_find_ele_by_xpath (line 1156) | def make_js_for_find_ele_by_xpath(xpath, type_txt, node_txt):
  function run_js (line 1192) | def run_js(page_or_ele, script, as_expr, timeout, args=None):
  function parse_js_result (line 1251) | def parse_js_result(page, ele, result, end_time):
  function convert_argument (line 1306) | def convert_argument(arg):
  class Pseudo (line 1322) | class Pseudo(object):
    method __init__ (line 1323) | def __init__(self, ele):
    method before (line 1327) | def before(self):
    method after (line 1335) | def after(self):
  function _check_ele (line 1343) | def _check_ele(ele, loc_data):

FILE: DrissionPage/_elements/chromium_element.pyi
  class ChromiumElement (line 30) | class ChromiumElement(DrissionElement):
    method __init__ (line 48) | def __init__(self,
    method __call__ (line 61) | def __call__(self,
    method __repr__ (line 72) | def __repr__(self) -> str: ...
    method __eq__ (line 74) | def __eq__(self, other: ChromiumElement) -> bool: ...
    method tag (line 77) | def tag(self) -> str:
    method html (line 82) | def html(self) -> str:
    method inner_html (line 87) | def inner_html(self) -> str:
    method attrs (line 92) | def attrs(self) -> dict:
    method text (line 97) | def text(self) -> str:
    method raw_text (line 102) | def raw_text(self) -> str:
    method set (line 107) | def set(self) -> ChromiumElementSetter:
    method states (line 112) | def states(self) -> ElementStates:
    method pseudo (line 117) | def pseudo(self) -> Pseudo:
    method rect (line 122) | def rect(self) -> ElementRect:
    method shadow_root (line 127) | def shadow_root(self) -> Union[None, ShadowRoot]:
    method sr (line 132) | def sr(self) -> Union[None, ShadowRoot]:
    method scroll (line 137) | def scroll(self) -> ElementScroller:
    method click (line 142) | def click(self) -> Clicker:
    method wait (line 147) | def wait(self) -> ElementWaiter:
    method select (line 152) | def select(self) -> Union[SelectElement, False]:
    method value (line 157) | def value(self) -> str:
    method parent (line 161) | def parent(self,
    method child (line 173) | def child(self,
    method prev (line 187) | def prev(self,
    method next (line 201) | def next(self,
    method before (line 215) | def before(self,
    method after (line 230) | def after(self,
    method children (line 245) | def children(self,
    method prevs (line 257) | def prevs(self,
    method nexts (line 269) | def nexts(self,
    method befores (line 281) | def befores(self,
    method afters (line 294) | def afters(self,
    method over (line 307) | def over(self, timeout: float = None) -> ChromiumElement:
    method offset (line 314) | def offset(self,
    method east (line 328) | def east(self, loc_or_pixel: Union[str, int, None] = None, index: int ...
    method south (line 336) | def south(self, loc_or_pixel: Union[str, int, None] = None, index: int...
    method west (line 344) | def west(self, loc_or_pixel: Union[str, int, None] = None, index: int ...
    method north (line 352) | def north(self, loc_or_pixel: Union[str, int, None] = None, index: int...
    method _get_relative_eles (line 360) | def _get_relative_eles(self,
    method check (line 371) | def check(self, uncheck: bool = False, by_js: bool = False) -> None:
    method attr (line 379) | def attr(self, name: str) -> Union[str, None]:
    method remove_attr (line 386) | def remove_attr(self, name: str) -> ChromiumElement:
    method property (line 393) | def property(self, name: str) -> Union[str, int, None]:
    method run_js (line 400) | def run_js(self, script: str, *args, as_expr: bool = False, timeout: f...
    method _run_js (line 410) | def _run_js(self, script: str, *args, as_expr: bool = False, timeout: ...
    method run_async_js (line 420) | def run_async_js(self, script: str, *args, as_expr: bool = False) -> N...
    method ele (line 429) | def ele(self,
    method eles (line 441) | def eles(self,
    method s_ele (line 451) | def s_ele(self,
    method s_eles (line 463) | def s_eles(self,
    method _find_elements (line 473) | def _find_elements(self,
    method style (line 489) | def style(self, style: str, pseudo_ele: str = '') -> str:
    method src (line 497) | def src(self, timeout: float = None, base64_to_bytes: bool = True) -> ...
    method save (line 505) | def save(self,
    method get_screenshot (line 519) | def get_screenshot(self,
    method input (line 535) | def input(self, vals: Any, clear: bool = False, by_js: bool = False) -...
    method clear (line 544) | def clear(self, by_js: bool = False) -> ChromiumElement:
    method _input_focus (line 551) | def _input_focus(self) -> None:
    method focus (line 555) | def focus(self) -> ChromiumElement:
    method hover (line 559) | def hover(self, offset_x: int = None, offset_y: int = None) -> Chromiu...
    method drag (line 567) | def drag(self, offset_x: int = 0, offset_y: int = 0, duration: float =...
    method drag_to (line 576) | def drag_to(self,
    method _get_obj_id (line 586) | def _get_obj_id(self, node_id: int = None, backend_id: int = None) -> ...
    method _get_node_id (line 588) | def _get_node_id(self, obj_id: str = None, backend_id: int = None) -> ...
    method _get_backend_id (line 590) | def _get_backend_id(self, node_id: int) -> int: ...
    method _refresh_id (line 592) | def _refresh_id(self) -> None:
    method _get_ele_path (line 596) | def _get_ele_path(self, xpath: bool = True) -> str:
    method _set_file_input (line 600) | def _set_file_input(self, files: Union[str, list, tuple]) -> None:
  class ShadowRoot (line 608) | class ShadowRoot(BaseElement):
    method __init__ (line 617) | def __init__(self, parent_ele: ChromiumElement, obj_id: str = None, ba...
    method __call__ (line 625) | def __call__(self,
    method __repr__ (line 638) | def __repr__(self) -> str: ...
    method __eq__ (line 640) | def __eq__(self, other: ShadowRoot) -> bool: ...
    method tag (line 643) | def tag(self) -> str:
    method html (line 648) | def html(self) -> str:
    method inner_html (line 653) | def inner_html(self) -> str:
    method states (line 658) | def states(self) -> ShadowRootStates:
    method run_js (line 662) | def run_js(self,
    method _run_js (line 676) | def _run_js(self,
    method run_async_js (line 690) | def run_async_js(self,
    method parent (line 704) | def parent(self,
    method child (line 716) | def child(self,
    method next (line 727) | def next(self,
    method before (line 738) | def before(self,
    method after (line 750) | def after(self,
    method children (line 762) | def children(self, locator: Union[Tuple[str, str], str] = '', timeout:...
    method nexts (line 770) | def nexts(self, locator: Union[Tuple[str, str], str] = '', timeout: fl...
    method befores (line 778) | def befores(self, locator: Union[Tuple[str, str], str] = '', timeout: ...
    method afters (line 787) | def afters(self, locator: Union[Tuple[str, str], str] = '', timeout: f...
    method ele (line 796) | def ele(self,
    method eles (line 808) | def eles(self,
    method s_ele (line 818) | def s_ele(self,
    method s_eles (line 830) | def s_eles(self, locator: Union[Tuple[str, str], str], timeout: float ...
    method _find_elements (line 838) | def _find_elements(self,
    method _get_node_id (line 854) | def _get_node_id(self, obj_id: str) -> int: ...
    method _get_obj_id (line 856) | def _get_obj_id(self, back_id: int) -> str: ...
    method _get_backend_id (line 858) | def _get_backend_id(self, node_id: int) -> int: ...
  function find_in_chromium_ele (line 861) | def find_in_chromium_ele(ele: ChromiumElement,
  function find_by_xpath (line 877) | def find_by_xpath(ele: ChromiumElement,
  function find_by_css (line 893) | def find_by_css(ele: ChromiumElement,
  function make_chromium_eles (line 907) | def make_chromium_eles(page: Union[ChromiumBase, ChromiumPage, WebPage, ...
  function make_js_for_find_ele_by_xpath (line 924) | def make_js_for_find_ele_by_xpath(xpath: str, type_txt: str, node_txt: s...
  function run_js (line 934) | def run_js(page_or_ele: Union[ChromiumBase, ChromiumElement, ShadowRoot],
  function parse_js_result (line 950) | def parse_js_result(page: ChromiumBase,
  function convert_argument (line 958) | def convert_argument(arg: Any) -> dict:
  class Pseudo (line 963) | class Pseudo(object):
    method __init__ (line 966) | def __init__(self, ele: ChromiumElement):
    method before (line 973) | def before(self) -> str:
    method after (line 978) | def after(self) -> str:

FILE: DrissionPage/_elements/none_element.py
  class NoneElement (line 12) | class NoneElement(object):
    method __init__ (line 13) | def __init__(self, page=None, method=None, args=None):
    method __call__ (line 26) | def __call__(self, *args, **kwargs):
    method __repr__ (line 32) | def __repr__(self):
    method __getattr__ (line 35) | def __getattr__(self, item):
    method __eq__ (line 48) | def __eq__(self, other):
    method __bool__ (line 51) | def __bool__(self):

FILE: DrissionPage/_elements/none_element.pyi
  class NoneElement (line 13) | class NoneElement(object):
    method __init__ (line 19) | def __init__(self,
    method __call__ (line 30) | def __call__(self, *args, **kwargs) -> NoneElement: ...
    method __repr__ (line 32) | def __repr__(self) -> str: ...
    method __getattr__ (line 34) | def __getattr__(self, item: str) -> str: ...
    method __eq__ (line 36) | def __eq__(self, other: Any) -> bool: ...
    method __bool__ (line 38) | def __bool__(self) -> bool: ...

FILE: DrissionPage/_elements/session_element.py
  class SessionElement (line 23) | class SessionElement(DrissionElement):
    method __init__ (line 25) | def __init__(self, ele, owner=None):
    method __repr__ (line 34) | def __repr__(self):
    method __call__ (line 38) | def __call__(self, locator, index=1, timeout=None):
    method __eq__ (line 41) | def __eq__(self, other):
    method inner_ele (line 45) | def inner_ele(self):
    method tag (line 49) | def tag(self):
    method html (line 53) | def html(self):
    method inner_html (line 58) | def inner_html(self):
    method attrs (line 63) | def attrs(self):
    method text (line 70) | def text(self):
    method raw_text (line 74) | def raw_text(self):
    method parent (line 77) | def parent(self, level_or_loc=1, index=1, timeout: float = None):
    method child (line 80) | def child(self, locator='', index=1, timeout=None, ele_only=True):
    method prev (line 83) | def prev(self, locator='', index=1, timeout=None, ele_only=True):
    method next (line 86) | def next(self, locator='', index=1, timeout=None, ele_only=True):
    method before (line 89) | def before(self, locator='', index=1, timeout=None, ele_only=True):
    method after (line 92) | def after(self, locator='', index=1, timeout=None, ele_only=True):
    method children (line 95) | def children(self, locator='', timeout=0, ele_only=True):
    method prevs (line 98) | def prevs(self, locator='', timeout=None, ele_only=True):
    method nexts (line 101) | def nexts(self, locator='', timeout=None, ele_only=True):
    method befores (line 104) | def befores(self, locator='', timeout=None, ele_only=True):
    method afters (line 107) | def afters(self, locator='', timeout=None, ele_only=True):
    method attr (line 110) | def attr(self, name):
    method ele (line 137) | def ele(self, locator, index=1, timeout=None):
    method eles (line 140) | def eles(self, locator, timeout=None):
    method s_ele (line 143) | def s_ele(self, locator=None, index=1):
    method s_eles (line 146) | def s_eles(self, locator):
    method _find_elements (line 149) | def _find_elements(self, locator, timeout, index=1, relative=False, ra...
    method _get_ele_path (line 152) | def _get_ele_path(self, xpath=True):
  function make_session_ele (line 169) | def make_session_ele(html_or_ele, loc=None, index=1, method=None):

FILE: DrissionPage/_elements/session_element.pyi
  class SessionElement (line 20) | class SessionElement(DrissionElement):
    method __init__ (line 23) | def __init__(self, ele: HtmlElement, owner: Union[SessionPage, None] =...
    method __call__ (line 28) | def __call__(self,
    method __repr__ (line 41) | def __repr__(self) -> str: ...
    method __eq__ (line 43) | def __eq__(self, other: SessionElement) -> bool: ...
    method inner_ele (line 46) | def inner_ele(self) -> HtmlElement: ...
    method tag (line 49) | def tag(self) -> str:
    method html (line 54) | def html(self) -> str:
    method inner_html (line 59) | def inner_html(self) -> str:
    method attrs (line 64) | def attrs(self) -> dict:
    method text (line 69) | def text(self) -> str:
    method raw_text (line 74) | def raw_text(self) -> str:
    method parent (line 78) | def parent(self,
    method child (line 90) | def child(self,
    method prev (line 104) | def prev(self,
    method next (line 118) | def next(self,
    method before (line 132) | def before(self,
    method after (line 147) | def after(self,
    method children (line 162) | def children(self,
    method prevs (line 174) | def prevs(self,
    method nexts (line 186) | def nexts(self,
    method befores (line 198) | def befores(self,
    method afters (line 211) | def afters(self,
    method attr (line 224) | def attr(self, name: str) -> Optional[str]:
    method ele (line 231) | def ele(self,
    method eles (line 243) | def eles(self,
    method s_ele (line 253) | def s_ele(self,
    method s_eles (line 263) | def s_eles(self, locator: Union[Tuple[str, str], str]) -> SessionEleme...
    method _find_elements (line 270) | def _find_elements(self,
    method _get_ele_path (line 286) | def _get_ele_path(self, xpath: bool = True) -> str:
  function make_session_ele (line 294) | def make_session_ele(html_or_ele: Union[str, SessionElement, SessionPage...

FILE: DrissionPage/_functions/browser.py
  function connect_browser (line 24) | def connect_browser(option):
  function get_launch_args (line 62) | def get_launch_args(opt):
  function set_prefs (line 106) | def set_prefs(opt):
  function set_flags (line 144) | def set_flags(opt):
  function test_connect (line 176) | def test_connect(ip, port):
  function _run_browser (line 197) | def _run_browser(port, path: str, args) -> Popen:
  function _make_leave_in_dict (line 214) | def _make_leave_in_dict(target_dict: dict, src: list, num: int, end: int...
  function _set_value_to_dict (line 230) | def _set_value_to_dict(target_dict: dict, src: list, value) -> None:
  function _remove_arg_from_dict (line 242) | def _remove_arg_from_dict(target_dict: dict, arg: str) -> None:
  function get_chrome_path (line 261) | def get_chrome_path(ini_path):

FILE: DrissionPage/_functions/browser.pyi
  function connect_browser (line 13) | def connect_browser(option: ChromiumOptions) -> bool:
  function get_launch_args (line 21) | def get_launch_args(opt: ChromiumOptions) -> list:
  function set_prefs (line 29) | def set_prefs(opt: ChromiumOptions) -> None:
  function set_flags (line 37) | def set_flags(opt: ChromiumOptions) -> None:
  function test_connect (line 45) | def test_connect(ip: str, port: Union[int, str], timeout: float = 30) ->...
  function get_chrome_path (line 55) | def get_chrome_path(ini_path: str) -> Union[str, None]:

FILE: DrissionPage/_functions/by.py
  class By (line 10) | class By:

FILE: DrissionPage/_functions/cli.py
  function main (line 20) | def main(set_browser_path, set_user_path, configs_to_here, launch_browser):
  function set_paths (line 35) | def set_paths(browser_path=None, user_data_path=None):

FILE: DrissionPage/_functions/cookies.py
  function cookie_to_dict (line 16) | def cookie_to_dict(cookie):
  function cookies_to_tuple (line 45) | def cookies_to_tuple(cookies):
  function set_session_cookies (line 72) | def set_session_cookies(session, cookies):
  function set_browser_cookies (line 87) | def set_browser_cookies(browser, cookies):
  function set_tab_cookies (line 96) | def set_tab_cookies(page, cookies):
  function is_cookie_in_driver (line 138) | def is_cookie_in_driver(page, cookie):
  function format_cookie (line 151) | def format_cookie(cookie):
  class CookiesList (line 210) | class CookiesList(list):
    method as_dict (line 211) | def as_dict(self):
    method as_str (line 214) | def as_str(self):
    method as_json (line 217) | def as_json(self):
  function _dict_cookies_to_tuple (line 222) | def _dict_cookies_to_tuple(cookies: dict):

FILE: DrissionPage/_functions/cookies.pyi
  function cookie_to_dict (line 18) | def cookie_to_dict(cookie: Union[Cookie, str, dict]) -> dict:
  function cookies_to_tuple (line 26) | def cookies_to_tuple(cookies: Union[RequestsCookieJar, list, tuple, str,...
  function set_session_cookies (line 34) | def set_session_cookies(session: Session,
  function set_browser_cookies (line 44) | def set_browser_cookies(browser: Chromium,
  function set_tab_cookies (line 54) | def set_tab_cookies(page: ChromiumBase,
  function is_cookie_in_driver (line 64) | def is_cookie_in_driver(page: ChromiumBase, cookie: dict) -> bool:
  function format_cookie (line 73) | def format_cookie(cookie: dict) -> dict:
  class CookiesList (line 81) | class CookiesList(list):
    method as_dict (line 82) | def as_dict(self) -> dict:
    method as_str (line 86) | def as_str(self) -> str:
    method as_json (line 90) | def as_json(self) -> str:
    method __next__ (line 94) | def __next__(self) -> dict: ...

FILE: DrissionPage/_functions/elements.py
  class SessionElementsList (line 16) | class SessionElementsList(list):
    method __init__ (line 17) | def __init__(self, owner=None, *args):
    method __getitem__ (line 21) | def __getitem__(self, item):
    method get (line 31) | def get(self):
    method filter (line 35) | def filter(self):
    method filter_one (line 39) | def filter_one(self):
  class ChromiumElementsList (line 43) | class ChromiumElementsList(SessionElementsList):
    method filter (line 46) | def filter(self):
    method filter_one (line 50) | def filter_one(self):
    method search (line 53) | def search(self, displayed=None, checked=None, selected=None, enabled=...
    method search_one (line 58) | def search_one(self, index=1, displayed=None, checked=None, selected=N...
  class SessionFilterOne (line 64) | class SessionFilterOne(object):
    method __init__ (line 65) | def __init__(self, _list):
    method __call__ (line 69) | def __call__(self, index=1):
    method tag (line 73) | def tag(self, name, equal=True):
    method attr (line 90) | def attr(self, name, value, equal=True):
    method text (line 93) | def text(self, text, fuzzy=True, contain=True):
    method _get_attr (line 112) | def _get_attr(self, name, value, method, equal=True):
  class SessionFilter (line 130) | class SessionFilter(SessionFilterOne):
    method __iter__ (line 132) | def __iter__(self):
    method __next__ (line 135) | def __next__(self):
    method __len__ (line 138) | def __len__(self):
    method __getitem__ (line 141) | def __getitem__(self, item):
    method get (line 145) | def get(self):
    method tag (line 148) | def tag(self, name, equal=True):
    method text (line 152) | def text(self, text, fuzzy=True, contain=True):
    method _get_attr (line 157) | def _get_attr(self, name, value, method, equal=True):
  class ChromiumFilterOne (line 163) | class ChromiumFilterOne(SessionFilterOne):
    method displayed (line 165) | def displayed(self, equal=True):
    method checked (line 168) | def checked(self, equal=True):
    method selected (line 171) | def selected(self, equal=True):
    method enabled (line 174) | def enabled(self, equal=True):
    method clickable (line 177) | def clickable(self, equal=True):
    method have_rect (line 180) | def have_rect(self, equal=True):
    method style (line 183) | def style(self, name, value, equal=True):
    method property (line 186) | def property(self, name, value, equal=True):
    method _any_state (line 189) | def _any_state(self, name, equal=True):
  class ChromiumFilter (line 206) | class ChromiumFilter(ChromiumFilterOne):
    method __iter__ (line 208) | def __iter__(self):
    method __next__ (line 211) | def __next__(self):
    method __len__ (line 214) | def __len__(self):
    method __getitem__ (line 217) | def __getitem__(self, item):
    method get (line 221) | def get(self):
    method search_one (line 224) | def search_one(self, index=1, displayed=None, checked=None, selected=N...
    method search (line 229) | def search(self, displayed=None, checked=None, selected=None, enabled=...
    method tag (line 234) | def tag(self, name, equal=True):
    method text (line 238) | def text(self, text, fuzzy=True, contain=True):
    method _get_attr (line 243) | def _get_attr(self, name, value, method, equal=True):
    method _any_state (line 248) | def _any_state(self, name, equal=True):
  class Getter (line 262) | class Getter(object):
    method __init__ (line 263) | def __init__(self, _list):
    method links (line 266) | def links(self):
    method texts (line 269) | def texts(self):
    method attrs (line 272) | def attrs(self, name):
  function get_eles (line 276) | def get_eles(locators, owner, any_one=False, first_ele=True, timeout=10):
  function get_frame (line 305) | def get_frame(owner, loc_ind_ele, timeout=None):
  function _attr_all (line 341) | def _attr_all(src_list, aim_list, name, value, method, equal=True):
  function _tag_all (line 353) | def _tag_all(src_list, aim_list, name, equal=True):
  function _text_all (line 366) | def _text_all(src_list, aim_list, text, fuzzy=True, contain=True):
  function _search (line 386) | def _search(_list, displayed=None, checked=None, selected=None, enabled=...
  function _search_one (line 421) | def _search_one(_list, index=1, displayed=None, checked=None, selected=N...

FILE: DrissionPage/_functions/elements.pyi
  class SessionElementsList (line 18) | class SessionElementsList(list):
    method __init__ (line 21) | def __init__(self,
    method __next__ (line 30) | def __next__(self) -> SessionElement: ...
    method __getitem__ (line 32) | def __getitem__(self, _i) -> Union[SessionElement, SessionElementsList...
    method __iter__ (line 34) | def __iter__(self) -> List[SessionElement]: ...
    method get (line 37) | def get(self) -> Getter:
    method filter (line 42) | def filter(self) -> SessionFilter:
    method filter_one (line 47) | def filter_one(self) -> SessionFilterOne:
  class ChromiumElementsList (line 52) | class ChromiumElementsList(SessionElementsList):
    method __init__ (line 55) | def __init__(self,
    method __next__ (line 64) | def __next__(self) -> ChromiumElement: ...
    method __getitem__ (line 66) | def __getitem__(self, _i) -> Union[ChromiumElement, ChromiumElementsLi...
    method __iter__ (line 68) | def __iter__(self) -> List[ChromiumElement]: ...
    method filter (line 71) | def filter(self) -> ChromiumFilter:
    method filter_one (line 76) | def filter_one(self) -> ChromiumFilterOne:
    method search (line 80) | def search(self,
    method search_one (line 102) | def search_one(self,
  class SessionFilterOne (line 127) | class SessionFilterOne(object):
    method __init__ (line 131) | def __init__(self, _list: SessionElementsList):
    method __call__ (line 137) | def __call__(self, index: int = 1) -> SessionFilterOne:
    method tag (line 144) | def tag(self, name: str, equal: bool = True) -> SessionElement:
    method attr (line 152) | def attr(self, name: str, value: str, equal: bool = True) -> SessionEl...
    method text (line 161) | def text(self, text: str, fuzzy: bool = True, contain: bool = True) ->...
    method _get_attr (line 170) | def _get_attr(self,
  class SessionFilter (line 184) | class SessionFilter(SessionFilterOne):
    method __iter__ (line 186) | def __iter__(self) -> Iterable[SessionElement]: ...
    method __next__ (line 188) | def __next__(self) -> SessionElement: ...
    method __len__ (line 190) | def __len__(self) -> int: ...
    method __getitem__ (line 192) | def __getitem__(self, item: int) -> SessionElement: ...
    method get (line 195) | def get(self) -> Getter:
    method tag (line 199) | def tag(self, name: str, equal: bool = True) -> SessionFilter:
    method attr (line 207) | def attr(self, name: str, value: str, equal: bool = True) -> SessionFi...
    method text (line 216) | def text(self, text: str, fuzzy: bool = True, contain: bool = True) ->...
    method _get_attr (line 225) | def _get_attr(self,
  class ChromiumFilterOne (line 239) | class ChromiumFilterOne(SessionFilterOne):
    method __init__ (line 242) | def __init__(self, _list: ChromiumElementsList):
    method __call__ (line 248) | def __call__(self, index: int = 1) -> ChromiumFilterOne:
    method tag (line 255) | def tag(self, name: str, equal: bool = True) -> SessionElement:
    method attr (line 263) | def attr(self, name: str, value: str, equal: bool = True) -> ChromiumE...
    method text (line 272) | def text(self,
    method displayed (line 284) | def displayed(self, equal: bool = True) -> ChromiumElement:
    method checked (line 291) | def checked(self, equal: bool = True) -> ChromiumElement:
    method selected (line 298) | def selected(self, equal: bool = True) -> ChromiumElement:
    method enabled (line 305) | def enabled(self, equal: bool = True) -> ChromiumElement:
    method clickable (line 312) | def clickable(self, equal: bool = True) -> ChromiumElement:
    method have_rect (line 319) | def have_rect(self, equal: bool = True) -> ChromiumElement:
    method style (line 326) | def style(self, name: str, value: str, equal: bool = True) -> Chromium...
    method property (line 335) | def property(self,
    method _get_attr (line 346) | def _get_attr(self,
    method _any_state (line 358) | def _any_state(self, name: str, equal: bool = True) -> ChromiumElement:
  class ChromiumFilter (line 367) | class ChromiumFilter(ChromiumFilterOne):
    method __iter__ (line 369) | def __iter__(self) -> Iterable[ChromiumElement]: ...
    method __next__ (line 371) | def __next__(self) -> ChromiumElement: ...
    method __len__ (line 373) | def __len__(self) -> int: ...
    method __getitem__ (line 375) | def __getitem__(self, item: int) -> ChromiumElement: ...
    method get (line 378) | def get(self) -> Getter:
    method tag (line 382) | def tag(self, name: str, equal: bool = True) -> ChromiumFilter:
    method attr (line 390) | def attr(self, name: str, value: str, equal: bool = True) -> ChromiumF...
    method text (line 399) | def text(self, text: str, fuzzy: bool = True, contain: bool = True) ->...
    method displayed (line 408) | def displayed(self, equal: bool = True) -> ChromiumFilter:
    method checked (line 415) | def checked(self, equal: bool = True) -> ChromiumFilter:
    method selected (line 422) | def selected(self, equal: bool = True) -> ChromiumFilter:
    method enabled (line 429) | def enabled(self, equal: bool = True) -> ChromiumFilter:
    method clickable (line 436) | def clickable(self, equal: bool = True) -> ChromiumFilter:
    method have_rect (line 443) | def have_rect(self, equal: bool = True) -> ChromiumFilter:
    method style (line 450) | def style(self, name: str, value: str, equal: bool = True) -> Chromium...
    method property (line 459) | def property(self,
    method search_one (line 470) | def search_one(self,
    method search (line 494) | def search(self,
    method _get_attr (line 516) | def _get_attr(self,
    method _any_state (line 528) | def _any_state(self, name: str, equal: bool = True) -> ChromiumFilter:
  class Getter (line 537) | class Getter(object):
    method __init__ (line 540) | def __init__(self, _list: SessionElementsList):
    method links (line 546) | def links(self) -> List[str]:
    method texts (line 550) | def texts(self) -> List[str]:
    method attrs (line 554) | def attrs(self, name: str) -> List[str]:
  function get_eles (line 562) | def get_eles(locators: Union[str, tuple, List[Union[str, tuple]]],
  function get_frame (line 579) | def get_frame(owner: BaseParser,

FILE: DrissionPage/_functions/keys.py
  class Keys (line 16) | class Keys:
  function keys_to_typing (line 346) | def keys_to_typing(value):
  function make_input_data (line 364) | def make_input_data(modifiers, key, key_up=False):
  function send_key (line 411) | def send_key(page, modifier, key):
  function input_text_or_keys (line 422) | def input_text_or_keys(page, text_or_keys):

FILE: DrissionPage/_functions/keys.pyi
  class Keys (line 13) | class Keys:
  function keys_to_typing (line 88) | def keys_to_typing(value: Union[str, int, list, tuple]) -> Tuple[int, str]:
  function make_input_data (line 94) | def make_input_data(modifiers: int,
  function send_key (line 106) | def send_key(page: ChromiumBase, modifier: int, key: str) -> None:
  function input_text_or_keys (line 116) | def input_text_or_keys(page: ChromiumBase, text_or_keys: Any) -> None:

FILE: DrissionPage/_functions/locator.py
  function locator_to_tuple (line 15) | def locator_to_tuple(loc):
  function _get_args (line 54) | def _get_args(text: str = '') -> dict:
  function _get_arg (line 74) | def _get_arg(text) -> list:
  function is_str_loc (line 85) | def is_str_loc(text):
  function is_selenium_loc (line 90) | def is_selenium_loc(loc):
  function get_loc (line 96) | def get_loc(loc, translate_css=False, css_mode=False):
  function str_to_xpath_loc (line 118) | def str_to_xpath_loc(loc):
  function str_to_css_loc (line 169) | def str_to_css_loc(loc):
  function _make_single_xpath_str (line 209) | def _make_single_xpath_str(tag: str, text: str) -> tuple:
  function _make_multi_xpath_str (line 272) | def _make_multi_xpath_str(tag: str, text: str) -> tuple:
  function _quotes_escape (line 348) | def _quotes_escape(search_str: str) -> str:
  function _make_multi_css_str (line 368) | def _make_multi_css_str(tag: str, text: str) -> tuple:
  function _make_single_css_str (line 416) | def _make_single_css_str(tag: str, text: str) -> tuple:
  function translate_loc (line 439) | def translate_loc(loc):
  function translate_css_loc (line 477) | def translate_css_loc(loc):
  function css_trans (line 517) | def css_trans(txt):
  function _preprocess (line 523) | def _preprocess(loc):

FILE: DrissionPage/_functions/locator.pyi
  function locator_to_tuple (line 11) | def locator_to_tuple(loc: str) -> dict:
  function is_str_loc (line 19) | def is_str_loc(text: str) -> bool:
  function is_selenium_loc (line 24) | def is_selenium_loc(loc: tuple) -> bool:
  function get_loc (line 29) | def get_loc(loc: Union[tuple, str],
  function str_to_xpath_loc (line 41) | def str_to_xpath_loc(loc: str) -> tuple:
  function str_to_css_loc (line 49) | def str_to_css_loc(loc: str) -> tuple:
  function translate_loc (line 57) | def translate_loc(loc: tuple) -> tuple:
  function translate_css_loc (line 65) | def translate_css_loc(loc: tuple) -> tuple:
  function css_trans (line 73) | def css_trans(txt: str) -> str:

FILE: DrissionPage/_functions/settings.py
  class Settings (line 13) | class Settings(object):
    method set_raise_when_ele_not_found (line 25) | def set_raise_when_ele_not_found(cls, on_off=True):
    method set_raise_when_click_failed (line 30) | def set_raise_when_click_failed(cls, on_off=True):
    method set_raise_when_wait_failed (line 35) | def set_raise_when_wait_failed(cls, on_off=True):
    method set_singleton_tab_obj (line 40) | def set_singleton_tab_obj(cls, on_off=True):
    method set_cdp_timeout (line 45) | def set_cdp_timeout(cls, second):
    method set_browser_connect_timeout (line 50) | def set_browser_connect_timeout(cls, second):
    method set_auto_handle_alert (line 55) | def set_auto_handle_alert(cls, accept=True):
    method set_language (line 60) | def set_language(cls, code):
    method set_suffixes_list (line 65) | def set_suffixes_list(cls, path):

FILE: DrissionPage/_functions/settings.pyi
  class Settings (line 14) | class Settings(object):
    method set_raise_when_ele_not_found (line 26) | def set_raise_when_ele_not_found(cls, on_off: bool = True) -> Settings:
    method set_raise_when_click_failed (line 34) | def set_raise_when_click_failed(cls, on_off: bool = True) -> Settings:
    method set_raise_when_wait_failed (line 42) | def set_raise_when_wait_failed(cls, on_off: bool = True) -> Settings:
    method set_singleton_tab_obj (line 50) | def set_singleton_tab_obj(cls, on_off: bool = True) -> Settings:
    method set_cdp_timeout (line 58) | def set_cdp_timeout(cls, second: float) -> Settings:
    method set_browser_connect_timeout (line 66) | def set_browser_connect_timeout(cls, second: float) -> Settings:
    method set_auto_handle_alert (line 74) | def set_auto_handle_alert(cls, accept: Optional[bool] = True) -> Setti...
    method set_language (line 82) | def set_language(cls, code: Literal['zh_cn', 'en']) -> Settings:
    method set_suffixes_list (line 90) | def set_suffixes_list(cls, path: Union[str, Path]) -> Settings:

FILE: DrissionPage/_functions/texts.py
  function get_txt_class (line 13) | def get_txt_class(lang=None):
  class Texts (line 35) | class Texts(object):
    method get (line 208) | def get(cls, item):
    method join (line 212) | def join(cls, *args, **kwargs):
  class English (line 219) | class English(Texts):

FILE: DrissionPage/_functions/tools.py
  class PortFinder (line 21) | class PortFinder(object):
    method __init__ (line 27) | def __init__(self, path=None):
    method get_port (line 37) | def get_port(self, scope=None):
  function port_is_using (line 63) | def port_is_using(ip, port):
  function clean_folder (line 72) | def clean_folder(folder_path, ignore=None):
  function show_or_hide_browser (line 84) | def show_or_hide_browser(tab, hide=True):
  function get_browser_progress_id (line 106) | def get_browser_progress_id(progress, address):
  function get_hwnds_from_pid (line 124) | def get_hwnds_from_pid(pid, title):
  function wait_until (line 144) | def wait_until(function, kwargs=None, timeout=10):
  function configs_to_here (line 156) | def configs_to_here(save_name=None):
  function raise_error (line 162) | def raise_error(result, browser, ignore=None, user=False):

FILE: DrissionPage/_functions/tools.pyi
  class PortFinder (line 17) | class PortFinder(object):
    method __init__ (line 24) | def __init__(self, path: Union[str, Path] = None):
    method get_port (line 31) | def get_port(scope: Tuple[int, int] = None) -> Tuple[int, str]:
  function port_is_using (line 39) | def port_is_using(ip: str, port: Union[str, int]) -> bool:
  function clean_folder (line 48) | def clean_folder(folder_path: Union[str, Path], ignore: Union[tuple, lis...
  function show_or_hide_browser (line 57) | def show_or_hide_browser(tab: ChromiumBase, hide: bool = True) -> None:
  function get_browser_progress_id (line 66) | def get_browser_progress_id(progress: Union[popen, None], address: str) ...
  function get_hwnds_from_pid (line 75) | def get_hwnds_from_pid(pid: Union[str, int], title: str) -> list:
  function wait_until (line 84) | def wait_until(function: callable, kwargs: dict = None, timeout: float =...
  function configs_to_here (line 94) | def configs_to_here(save_name: Union[Path, str] = None) -> None:
  function raise_error (line 102) | def raise_error(result: dict, browser: Chromium, ignore=None, user: bool...

FILE: DrissionPage/_functions/web.py
  function get_ele_txt (line 20) | def get_ele_txt(e):
  function format_html (line 106) | def format_html(text):
  function location_in_viewport (line 110) | def location_in_viewport(page, loc_x, loc_y):
  function offset_scroll (line 121) | def offset_scroll(ele, offset_x, offset_y):
  function make_absolute_link (line 137) | def make_absolute_link(link, baseURI=None):
  function is_js_func (line 160) | def is_js_func(func):
  function get_blob (line 169) | def get_blob(page, url, as_bytes=True):
  function save_page (line 198) | def save_page(tab, path=None, name=None, as_pdf=False, kwargs=None):
  function get_mhtml (line 221) | def get_mhtml(page, path=None, name=None):
  function get_pdf (line 234) | def get_pdf(page, path=None, name=None, kwargs=None):
  function tree (line 257) | def tree(ele_or_page, text=False, show_js=False, show_css=False):
  function format_headers (line 304) | def format_headers(txt):

FILE: DrissionPage/_functions/web.pyi
  function get_ele_txt (line 18) | def get_ele_txt(e: DrissionElement) -> str:
  function format_html (line 26) | def format_html(text: str) -> str:
  function location_in_viewport (line 34) | def location_in_viewport(page: ChromiumBase, loc_x: float, loc_y: float)...
  function offset_scroll (line 44) | def offset_scroll(ele: ChromiumElement, offset_x: float, offset_y: float...
  function make_absolute_link (line 55) | def make_absolute_link(link: str, baseURI: str = None) -> str:
  function is_js_func (line 64) | def is_js_func(func: str) -> bool:
  function get_blob (line 69) | def get_blob(page: ChromiumBase, url: str, as_bytes: bool = True) -> bytes:
  function save_page (line 79) | def save_page(tab: Union[ChromiumPage, ChromiumTab],
  function get_mhtml (line 95) | def get_mhtml(page: Union[ChromiumPage, ChromiumTab],
  function get_pdf (line 107) | def get_pdf(page: Union[ChromiumPage, ChromiumTab],
  function tree (line 121) | def tree(ele_or_page: BaseParser,
  function format_headers (line 135) | def format_headers(txt: str) -> dict:

FILE: DrissionPage/_pages/chromium_base.py
  class ChromiumBase (line 42) | class ChromiumBase(BasePage):
    method __init__ (line 43) | def __init__(self, browser, target_id=None):
    method __call__ (line 71) | def __call__(self, locator, index=1, timeout=None):
    method _d_set_runtime_settings (line 74) | def _d_set_runtime_settings(self):
    method _connect_browser (line 77) | def _connect_browser(self, target_id=None):
    method _driver_init (line 111) | def _driver_init(self, target_id):
    method _get_document (line 137) | def _get_document(self, timeout=10):
    method _onFrameDetached (line 173) | def _onFrameDetached(self, **kwargs):
    method _onFrameAttached (line 176) | def _onFrameAttached(self, **kwargs):
    method _onFrameStartedLoading (line 179) | def _onFrameStartedLoading(self, **kwargs):
    method _onFrameNavigated (line 191) | def _onFrameNavigated(self, **kwargs):
    method _onDomContentEventFired (line 199) | def _onDomContentEventFired(self, **kwargs):
    method _onLoadEventFired (line 206) | def _onLoadEventFired(self, **kwargs):
    method _onFrameStoppedLoading (line 211) | def _onFrameStoppedLoading(self, **kwargs):
    method _onFileChooserOpened (line 218) | def _onFileChooserOpened(self, **kwargs):
    method _wait_to_stop (line 229) | def _wait_to_stop(self):
    method wait (line 238) | def wait(self):
    method set (line 244) | def set(self):
    method screencast (line 250) | def screencast(self):
    method actions (line 256) | def actions(self):
    method listen (line 263) | def listen(self):
    method states (line 269) | def states(self):
    method scroll (line 275) | def scroll(self):
    method rect (line 282) | def rect(self):
    method console (line 289) | def console(self):
    method timeout (line 295) | def timeout(self):
    method timeouts (line 299) | def timeouts(self):
    method browser (line 305) | def browser(self):
    method driver (line 309) | def driver(self):
    method title (line 315) | def title(self):
    method url (line 319) | def url(self):
    method _browser_url (line 323) | def _browser_url(self):
    method html (line 327) | def html(self):
    method json (line 332) | def json(self):
    method tab_id (line 339) | def tab_id(self):
    method _target_id (line 343) | def _target_id(self):
    method active_ele (line 347) | def active_ele(self):
    method load_mode (line 351) | def load_mode(self):
    method user_agent (line 355) | def user_agent(self):
    method upload_list (line 359) | def upload_list(self):
    method session (line 363) | def session(self):
    method _js_ready_state (line 369) | def _js_ready_state(self):
    method run_cdp (line 377) | def run_cdp(self, cmd, **cmd_args):
    method run_cdp_loaded (line 381) | def run_cdp_loaded(self, cmd, **cmd_args):
    method _run_cdp (line 386) | def _run_cdp(self, cmd, **cmd_args):
    method _run_cdp_loaded (line 391) | def _run_cdp_loaded(self, cmd, **cmd_args):
    method run_js (line 395) | def run_js(self, script, *args, as_expr=False, timeout=None):
    method run_js_loaded (line 398) | def run_js_loaded(self, script, *args, as_expr=False, timeout=None):
    method _run_js (line 402) | def _run_js(self, script, *args, as_expr=False, timeout=None):
    method _run_js_loaded (line 405) | def _run_js_loaded(self, script, *args, as_expr=False, timeout=None):
    method run_async_js (line 409) | def run_async_js(self, script, *args, as_expr=False):
    method get (line 412) | def get(self, url, show_errmsg=False, retry=None, interval=None, timeo...
    method cookies (line 418) | def cookies(self, all_domains=False, all_info=False):
    method ele (line 429) | def ele(self, locator, index=1, timeout=None):
    method eles (line 432) | def eles(self, locator, timeout=None):
    method s_ele (line 435) | def s_ele(self, locator=None, index=1, timeout=None):
    method s_eles (line 442) | def s_eles(self, locator, timeout=None):
    method _find_elements (line 446) | def _find_elements(self, locator, timeout, index=1, relative=False, ra...
    method refresh (line 510) | def refresh(self, ignore_cache=False):
    method forward (line 515) | def forward(self, steps=1):
    method back (line 518) | def back(self, steps=1):
    method _forward_or_back (line 521) | def _forward_or_back(self, steps):
    method stop_loading (line 543) | def stop_loading(self):
    method remove_ele (line 554) | def remove_ele(self, loc_or_ele):
    method add_ele (line 561) | def add_ele(self, html_or_info, insert_to=None, before=None):
    method get_frame (line 616) | def get_frame(self, loc_ind_ele, timeout=None):
    method get_frames (line 619) | def get_frames(self, locator=None, timeout=None):
    method session_storage (line 624) | def session_storage(self, item=None):
    method local_storage (line 628) | def local_storage(self, item=None):
    method get_screenshot (line 632) | def get_screenshot(self, path=None, name=None, as_bytes=None, as_base6...
    method add_init_js (line 637) | def add_init_js(self, script):
    method remove_init_js (line 643) | def remove_init_js(self, script_id=None):
    method clear_cache (line 653) | def clear_cache(self, session_storage=True, local_storage=True, cache=...
    method disconnect (line 672) | def disconnect(self):
    method reconnect (line 679) | def reconnect(self, wait=0):
    method handle_alert (line 688) | def handle_alert(self, accept=True, send=None, timeout=None, next_one=...
    method _handle_alert (line 696) | def _handle_alert(self, accept=True, send=None, timeout=None, next_one...
    method _on_alert_open (line 719) | def _on_alert_open(self, **kwargs):
    method _on_alert_close (line 737) | def _on_alert_close(self, **kwargs):
    method _wait_loaded (line 746) | def _wait_loaded(self, timeout=None):
    method _d_connect (line 765) | def _d_connect(self, to_url, times=0, interval=1, show_errmsg=False, t...
    method _get_screenshot (line 813) | def _get_screenshot(self, path=None, name=None, as_bytes=None, as_base...
  class Timeout (line 893) | class Timeout(object):
    method __init__ (line 894) | def __init__(self, base=None, page_load=None, script=None):
    method __repr__ (line 899) | def __repr__(self):
    method as_dict (line 903) | def as_dict(self):
  class Alert (line 907) | class Alert(object):
    method __init__ (line 908) | def __init__(self, auto=None):
  function close_privacy_dialog (line 920) | def close_privacy_dialog(page, tid):

FILE: DrissionPage/_pages/chromium_base.pyi
  class ChromiumBase (line 38) | class ChromiumBase(BasePage):
    method __init__ (line 72) | def __init__(self,
    method __call__ (line 81) | def __call__(self,
    method _d_set_runtime_settings (line 94) | def _d_set_runtime_settings(self) -> None: ...
    method _connect_browser (line 96) | def _connect_browser(self, target_id: str = None) -> None:
    method _driver_init (line 103) | def _driver_init(self, target_id: str) -> None:
    method _get_document (line 110) | def _get_document(self, timeout: float = 10) -> bool:
    method _onFrameDetached (line 117) | def _onFrameDetached(self, **kwargs) -> None: ...
    method _onFrameAttached (line 119) | def _onFrameAttached(self, **kwargs) -> None: ...
    method _onFrameStartedLoading (line 121) | def _onFrameStartedLoading(self, **kwargs):
    method _onFrameNavigated (line 125) | def _onFrameNavigated(self, **kwargs):
    method _onDomContentEventFired (line 129) | def _onDomContentEventFired(self, **kwargs):
    method _onLoadEventFired (line 133) | def _onLoadEventFired(self, **kwargs):
    method _onFrameStoppedLoading (line 137) | def _onFrameStoppedLoading(self, **kwargs):
    method _onFileChooserOpened (line 141) | def _onFileChooserOpened(self, **kwargs):
    method _wait_to_stop (line 145) | def _wait_to_stop(self):
    method wait (line 150) | def wait(self) -> BaseWaiter:
    method set (line 155) | def set(self) -> ChromiumBaseSetter:
    method screencast (line 160) | def screencast(self) -> Screencast:
    method actions (line 165) | def actions(self) -> Actions:
    method listen (line 170) | def listen(self) -> Listener:
    method states (line 175) | def states(self) -> PageStates:
    method scroll (line 180) | def scroll(self) -> PageScroller:
    method rect (line 185) | def rect(self) -> Union[TabRect, FrameRect]:
    method console (line 190) | def console(self) -> Console:
    method timeout (line 195) | def timeout(self) -> float:
    method timeouts (line 200) | def timeouts(self) -> Timeout:
    method browser (line 205) | def browser(self) -> Chromium:
    method driver (line 210) | def driver(self) -> Driver:
    method title (line 215) | def title(self) -> str:
    method url (line 220) | def url(self) -> str:
    method _browser_url (line 225) | def _browser_url(self) -> str:
    method html (line 230) | def html(self) -> str:
    method json (line 235) | def json(self) -> Union[dict, None]:
    method tab_id (line 240) | def tab_id(self) -> str:
    method _target_id (line 245) | def _target_id(self) -> str:
    method active_ele (line 250) | def active_ele(self) -> ChromiumElement:
    method load_mode (line 255) | def load_mode(self) -> Literal['none', 'normal', 'eager']:
    method user_agent (line 260) | def user_agent(self) -> str:
    method upload_list (line 265) | def upload_list(self) -> list:
    method session (line 270) | def session(self) -> Session:
    method _js_ready_state (line 275) | def _js_ready_state(self) -> str:
    method run_cdp (line 279) | def run_cdp(self, cmd: str, **cmd_args) -> dict:
    method run_cdp_loaded (line 287) | def run_cdp_loaded(self, cmd: str, **cmd_args) -> dict:
    method _run_cdp (line 295) | def _run_cdp(self, cmd: str, **cmd_args) -> dict:
    method _run_cdp_loaded (line 303) | def _run_cdp_loaded(self, cmd: str, **cmd_args) -> dict:
    method run_js (line 311) | def run_js(self, script: Union[str, Path], *args, as_expr: bool = Fals...
    method run_js_loaded (line 321) | def run_js_loaded(self, script: Union[str, Path], *args, as_expr: bool...
    method _run_js (line 331) | def _run_js(self, script: Union[str, Path], *args, as_expr: bool = Fal...
    method _run_js_loaded (line 341) | def _run_js_loaded(self, script: Union[str, Path], *args, as_expr: boo...
    method run_async_js (line 351) | def run_async_js(self, script: Union[str, Path], *args, as_expr: bool ...
    method get (line 360) | def get(self, url: str, show_errmsg: bool = False, retry: int = None,
    method cookies (line 372) | def cookies(self, all_domains: bool = False, all_info: bool = False) -...
    method ele (line 380) | def ele(self,
    method eles (line 392) | def eles(self,
    method s_ele (line 402) | def s_ele(self,
    method s_eles (line 414) | def s_eles(self,
    method _find_elements (line 424) | def _find_elements(self,
    method refresh (line 440) | def refresh(self, ignore_cache: bool = False) -> None:
    method forward (line 447) | def forward(self, steps: int = 1) -> None:
    method back (line 454) | def back(self, steps: int = 1) -> None:
    method _forward_or_back (line 461) | def _forward_or_back(self, steps: int) -> None:
    method stop_loading (line 468) | def stop_loading(self) -> None:
    method remove_ele (line 472) | def remove_ele(self, loc_or_ele: Union[ChromiumElement, ChromiumFrame,...
    method add_ele (line 479) | def add_ele(self,
    method get_frame (line 492) | def get_frame(self,
    method get_frames (line 502) | def get_frames(self,
    method session_storage (line 512) | def session_storage(self, item: str = None) -> Union[str, dict, None]:
    method local_storage (line 519) | def local_storage(self, item: str = None) -> Union[str, dict, None]:
    method get_screenshot (line 526) | def get_screenshot(self, path: [str, Path] = None, name: str = None, a...
    method add_init_js (line 541) | def add_init_js(self, script: str) -> str:
    method remove_init_js (line 548) | def remove_init_js(self, script_id: str = None) -> None:
    method clear_cache (line 555) | def clear_cache(self, session_storage: bool = True, local_storage: boo...
    method disconnect (line 566) | def disconnect(self) -> None:
    method reconnect (line 570) | def reconnect(self, wait: float = 0) -> None:
    method handle_alert (line 577) | def handle_alert(self,
    method _handle_alert (line 591) | def _handle_alert(self,
    method _on_alert_open (line 605) | def _on_alert_open(self, **kwargs):
    method _on_alert_close (line 609) | def _on_alert_close(self, **kwargs):
    method _wait_loaded (line 613) | def _wait_loaded(self, timeout: float = None) -> bool:
    method _d_connect (line 620) | def _d_connect(self, to_url: str, times: int = 0, interval: float = 1,...
    method _get_screenshot (line 632) | def _get_screenshot(self, path: [str, Path] = None, name: str = None, ...
  class Timeout (line 649) | class Timeout(object):
    method __init__ (line 655) | def __init__(self, base=None, page_load=None, script=None):
    method as_dict (line 664) | def as_dict(self) -> dict:
  class Alert (line 669) | class Alert(object):
    method __init__ (line 681) | def __init__(self, auto: bool = None): ...

FILE: DrissionPage/_pages/chromium_frame.py
  class ChromiumFrame (line 24) | class ChromiumFrame(ChromiumBase):
    method __new__ (line 27) | def __new__(cls, owner, ele, info=None):
    method __init__ (line 39) | def __init__(self, owner, ele, info=None):
    method __call__ (line 70) | def __call__(self, locator, index=1, timeout=None):
    method __repr__ (line 73) | def __repr__(self):
    method __eq__ (line 77) | def __eq__(self, other):
    method _d_set_runtime_settings (line 80) | def _d_set_runtime_settings(self):
    method _driver_init (line 89) | def _driver_init(self, target_id, is_init=True):
    method _reload (line 100) | def _reload(self):
    method _get_document (line 143) | def _get_document(self, timeout=10):
    method _onInspectorDetached (line 173) | def _onInspectorDetached(self, **kwargs):
    method _onFrameDetached (line 177) | def _onFrameDetached(self, **kwargs):
    method scroll (line 186) | def scroll(self):
    method set (line 193) | def set(self):
    method states (line 199) | def states(self):
    method wait (line 205) | def wait(self):
    method rect (line 211) | def rect(self):
    method listen (line 217) | def listen(self):
    method _obj_id (line 225) | def _obj_id(self):
    method _node_id (line 229) | def _node_id(self):
    method owner (line 233) | def owner(self):
    method frame_ele (line 237) | def frame_ele(self):
    method tag (line 241) | def tag(self):
    method url (line 245) | def url(self):
    method html (line 252) | def html(self):
    method inner_html (line 259) | def inner_html(self):
    method link (line 263) | def link(self):
    method title (line 267) | def title(self):
    method attrs (line 272) | def attrs(self):
    method active_ele (line 276) | def active_ele(self):
    method xpath (line 280) | def xpath(self):
    method css_path (line 284) | def css_path(self):
    method tab (line 288) | def tab(self):
    method tab_id (line 292) | def tab_id(self):
    method download_path (line 296) | def download_path(self):
    method sr (line 300) | def sr(self):
    method shadow_root (line 304) | def shadow_root(self):
    method child_count (line 308) | def child_count(self):
    method _js_ready_state (line 312) | def _js_ready_state(self):
    method refresh (line 327) | def refresh(self):
    method property (line 330) | def property(self, name):
    method attr (line 333) | def attr(self, name):
    method remove_attr (line 336) | def remove_attr(self, name):
    method style (line 339) | def style(self, style, pseudo_ele=''):
    method run_js (line 342) | def run_js(self, script, *args, as_expr=False, timeout=None):
    method _run_js (line 345) | def _run_js(self, script, *args, as_expr=False, timeout=None):
    method parent (line 351) | def parent(self, level_or_loc=1, index=1, timeout=0):
    method prev (line 354) | def prev(self, locator='', index=1, timeout=0, ele_only=True):
    method next (line 357) | def next(self, locator='', index=1, timeout=0, ele_only=True):
    method before (line 360) | def before(self, locator='', index=1, timeout=None, ele_only=True):
    method after (line 363) | def after(self, locator='', index=1, timeout=None, ele_only=True):
    method prevs (line 366) | def prevs(self, locator='', timeout=0, ele_only=True):
    method nexts (line 369) | def nexts(self, locator='', timeout=0, ele_only=True):
    method befores (line 372) | def befores(self, locator='', timeout=None, ele_only=True):
    method afters (line 375) | def afters(self, locator='', timeout=None, ele_only=True):
    method get_screenshot (line 378) | def get_screenshot(self, path=None, name=None, as_bytes=None, as_base6...
    method _get_screenshot (line 381) | def _get_screenshot(self, path=None, name=None, as_bytes: [bool, str] ...
    method _find_elements (line 449) | def _find_elements(self, locator, timeout, index=1, relative=False, ra...
    method _is_inner_frame (line 456) | def _is_inner_frame(self):

FILE: DrissionPage/_pages/chromium_frame.pyi
  class ChromiumFrame (line 24) | class ChromiumFrame(ChromiumBase):
    method __init__ (line 39) | def __init__(self,
    method __call__ (line 50) | def __call__(self,
    method __repr__ (line 62) | def __repr__(self) -> str: ...
    method __eq__ (line 64) | def __eq__(self, other: ChromiumFrame) -> bool: ...
    method _d_set_runtime_settings (line 66) | def _d_set_runtime_settings(self) -> None:
    method _driver_init (line 70) | def _driver_init(self, target_id: str, is_init: bool = True) -> None:
    method _reload (line 77) | def _reload(self) -> None:
    method _get_document (line 81) | def _get_document(self, timeout: float = 10) -> bool:
    method _onFrameStoppedLoading (line 88) | def _onFrameStoppedLoading(self, **kwargs): ...
    method _onInspectorDetached (line 90) | def _onInspectorDetached(self, **kwargs): ...
    method scroll (line 93) | def scroll(self) -> FrameScroller:
    method set (line 98) | def set(self) -> ChromiumFrameSetter:
    method states (line 103) | def states(self) -> FrameStates:
    method wait (line 108) | def wait(self) -> FrameWaiter:
    method rect (line 113) | def rect(self) -> FrameRect:
    method listen (line 118) | def listen(self) -> FrameListener:
    method _obj_id (line 123) | def _obj_id(self) -> str: ...
    method _node_id (line 126) | def _node_id(self) -> int: ...
    method owner (line 129) | def owner(self) -> ChromiumBase:
    method frame_ele (line 134) | def frame_ele(self) -> ChromiumElement:
    method tag (line 139) | def tag(self) -> str:
    method url (line 144) | def url(self) -> str:
    method html (line 149) | def html(self) -> str:
    method inner_html (line 154) | def inner_html(self) -> str:
    method link (line 159) | def link(self) -> str:
    method title (line 164) | def title(self) -> str:
    method attrs (line 169) | def attrs(self) -> dict:
    method active_ele (line 174) | def active_ele(self) -> ChromiumElement:
    method xpath (line 179) | def xpath(self) -> str:
    method css_path (line 184) | def css_path(self) -> str:
    method tab (line 189) | def tab(self) -> Union[ChromiumTab, MixTab]:
    method tab_id (line 194) | def tab_id(self) -> str:
    method download_path (line 199) | def download_path(self) -> str:
    method sr (line 204) | def sr(self) -> Union[None, ShadowRoot]:
    method shadow_root (line 209) | def shadow_root(self) -> Union[None, ShadowRoot]:
    method child_count (line 214) | def child_count(self) -> int:
    method _js_ready_state (line 219) | def _js_ready_state(self) -> Literal['loading', 'interactive', 'comple...
    method refresh (line 223) | def refresh(self) -> None:
    method property (line 227) | def property(self, name: str) -> Union[str, None]:
    method attr (line 234) | def attr(self, name: str) -> Union[str, None]:
    method remove_attr (line 241) | def remove_attr(self, name: str) -> None:
    method style (line 248) | def style(self, style: str, pseudo_ele: str = '') -> str:
    method run_js (line 256) | def run_js(self,
    method _run_js (line 270) | def _run_js(self,
    method parent (line 284) | def parent(self,
    method prev (line 296) | def prev(self,
    method next (line 310) | def next(self,
    method before (line 324) | def before(self,
    method after (line 339) | def after(self,
    method prevs (line 354) | def prevs(self,
    method nexts (line 366) | def nexts(self,
    method befores (line 378) | def befores(self,
    method afters (line 391) | def afters(self,
    method get_screenshot (line 404) | def get_screenshot(self,
    method _get_screenshot (line 418) | def _get_screenshot(self,
    method _find_elements (line 440) | def _find_elements(self,
    method _is_inner_frame (line 456) | def _is_inner_frame(self) -> bool:

FILE: DrissionPage/_pages/chromium_page.py
  class ChromiumPage (line 18) | class ChromiumPage(ChromiumBase):
    method __new__ (line 21) | def __new__(cls, addr_or_opts=None, tab_id=None, timeout=None):
    method __init__ (line 35) | def __init__(self, addr_or_opts=None, tab_id=None, timeout=None):
    method __repr__ (line 48) | def __repr__(self):
    method _d_set_runtime_settings (line 51) | def _d_set_runtime_settings(self):
    method set (line 61) | def set(self):
    method wait (line 67) | def wait(self):
    method browser (line 73) | def browser(self):
    method tabs_count (line 77) | def tabs_count(self):
    method tab_ids (line 81) | def tab_ids(self):
    method latest_tab (line 85) | def latest_tab(self):
    method process_id (line 89) | def process_id(self):
    method browser_version (line 93) | def browser_version(self):
    method address (line 97) | def address(self):
    method download_path (line 101) | def download_path(self):
    method save (line 104) | def save(self, path=None, name=None, as_pdf=False, **kwargs):
    method get_tab (line 107) | def get_tab(self, id_or_num=None, title=None, url=None, tab_type='page...
    method get_tabs (line 111) | def get_tabs(self, title=None, url=None, tab_type='page', as_id=False):
    method new_tab (line 114) | def new_tab(self, url=None, new_window=False, background=False, new_co...
    method activate_tab (line 118) | def activate_tab(self, id_ind_tab):
    method close (line 121) | def close(self):
    method close_tabs (line 124) | def close_tabs(self, tabs_or_ids, others=False):
    method quit (line 127) | def quit(self, timeout=5, force=True, del_data=False):
    method _on_disconnect (line 130) | def _on_disconnect(self):

FILE: DrissionPage/_pages/chromium_page.pyi
  class ChromiumPage (line 20) | class ChromiumPage(ChromiumBase):
    method __new__ (line 28) | def __new__(cls,
    method __init__ (line 37) | def __init__(self,
    method set (line 47) | def set(self) -> ChromiumPageSetter:
    method wait (line 52) | def wait(self) -> ChromiumPageWaiter:
    method browser (line 57) | def browser(self) -> Chromium:
    method tabs_count (line 62) | def tabs_count(self) -> int:
    method tab_ids (line 67) | def tab_ids(self) -> List[str]:
    method latest_tab (line 72) | def latest_tab(self) -> Union[ChromiumTab, ChromiumPage, str]:
    method process_id (line 78) | def process_id(self) -> Optional[int]:
    method browser_version (line 83) | def browser_version(self) -> str:
    method address (line 88) | def address(self) -> str:
    method save (line 92) | def save(self,
    method get_tab (line 143) | def get_tab(self,
    method get_tabs (line 159) | def get_tabs(self,
    method new_tab (line 173) | def new_tab(self,
    method activate_tab (line 187) | def activate_tab(self,
    method close (line 195) | def close(self) -> None:
    method close_tabs (line 199) | def close_tabs(self,
    method quit (line 210) | def quit(self,
    method _on_disconnect (line 222) | def _on_disconnect(self) -> None:

FILE: DrissionPage/_pages/chromium_tab.py
  class ChromiumTab (line 18) | class ChromiumTab(ChromiumBase):
    method __new__ (line 21) | def __new__(cls, browser, tab_id):
    method __init__ (line 31) | def __init__(self, browser, tab_id):
    method __repr__ (line 40) | def __repr__(self):
    method _d_set_runtime_settings (line 43) | def _d_set_runtime_settings(self):
    method close (line 53) | def close(self, others=False):
    method set (line 60) | def set(self):
    method wait (line 66) | def wait(self):
    method save (line 71) | def save(self, path=None, name=None, as_pdf=False, **kwargs):
    method _on_disconnect (line 74) | def _on_disconnect(self):

FILE: DrissionPage/_pages/chromium_tab.pyi
  class ChromiumTab (line 18) | class ChromiumTab(ChromiumBase):
    method __new__ (line 24) | def __new__(cls, browser: Chromium, tab_id: str):
    method __init__ (line 31) | def __init__(self, browser: Chromium, tab_id: str):
    method _d_set_runtime_settings (line 38) | def _d_set_runtime_settings(self) -> None:
    method close (line 42) | def close(self, others: bool = False) -> None:
    method set (line 50) | def set(self) -> TabSetter:
    method wait (line 55) | def wait(self) -> TabWaiter:
    method save (line 59) | def save(self,
    method _on_disconnect (line 110) | def _on_disconnect(self): ...

FILE: DrissionPage/_pages/mix_tab.py
  class MixTab (line 17) | class MixTab(SessionPage, ChromiumTab, BasePage):
    method __init__ (line 18) | def __init__(self, browser, tab_id):
    method __call__ (line 31) | def __call__(self, locator, index=1, timeout=None):
    method __repr__ (line 35) | def __repr__(self):
    method set (line 39) | def set(self):
    method url (line 45) | def url(self):
    method _browser_url (line 49) | def _browser_url(self):
    method title (line 53) | def title(self):
    method raw_data (line 57) | def raw_data(self):
    method html (line 61) | def html(self):
    method json (line 65) | def json(self):
    method response (line 69) | def response(self):
    method mode (line 73) | def mode(self):
    method user_agent (line 77) | def user_agent(self):
    method _session_url (line 81) | def _session_url(self):
    method timeout (line 85) | def timeout(self):
    method get (line 88) | def get(self, url, show_errmsg=False, retry=None, interval=None, timeo...
    method post (line 98) | def post(self, url, show_errmsg=False, retry=None, interval=None, time...
    method ele (line 108) | def ele(self, locator, index=1, timeout=None):
    method eles (line 112) | def eles(self, locator, timeout=None):
    method s_ele (line 115) | def s_ele(self, locator=None, index=1, timeout=None):
    method s_eles (line 119) | def s_eles(self, locator, timeout=None):
    method change_mode (line 123) | def change_mode(self, mode=None, go=True, copy_cookies=True):
    method cookies_to_session (line 162) | def cookies_to_session(self, copy_user_agent=True):
    method cookies_to_browser (line 172) | def cookies_to_browser(self):
    method cookies (line 177) | def cookies(self, all_domains=False, all_info=False):
    method close (line 181) | def close(self, others=False, session=False):
    method _find_elements (line 191) | def _find_elements(self, locator, timeout, index=1, relative=False, ra...
    method _set_session_options (line 195) | def _set_session_options(self, session_or_options=None):

FILE: DrissionPage/_pages/mix_tab.pyi
  class MixTab (line 25) | class MixTab(SessionPage, ChromiumTab):
    method __init__ (line 30) | def __init__(self, browser: Chromium, tab_id: str):
    method __call__ (line 37) | def __call__(self,
    method set (line 51) | def set(self) -> MixTabSetter:
    method wait (line 56) | def wait(self) -> MixTabWaiter:
    method url (line 61) | def url(self) -> Union[str, None]:
    method _browser_url (line 66) | def _browser_url(self) -> Union[str, None]:
    method title (line 71) | def title(self) -> str:
    method raw_data (line 76) | def raw_data(self) -> Union[str, bytes]:
    method html (line 81) | def html(self) -> str:
    method json (line 86) | def json(self) -> dict:
    method response (line 91) | def response(self) -> Response:
    method mode (line 96) | def mode(self) -> Literal['s', 'd']:
    method user_agent (line 101) | def user_agent(self) -> str:
    method session (line 106) | def session(self) -> Session:
    method _session_url (line 111) | def _session_url(self) -> str:
    method timeout (line 116) | def timeout(self) -> float:
    method get (line 120) | def get(self,
    method post (line 162) | def post(self,
    method ele (line 204) | def ele(self,
    method eles (line 216) | def eles(self,
    method s_ele (line 226) | def s_ele(self,
    method s_eles (line 238) | def s_eles(self, locator: Union[Tuple[str, str], str], timeout: float ...
    method change_mode (line 246) | def change_mode(self, mode: str = None, go: bool = True, copy_cookies:...
    method cookies_to_session (line 257) | def cookies_to_session(self, copy_user_agent: bool = True) -> None:
    method cookies_to_browser (line 264) | def cookies_to_browser(self) -> None:
    method cookies (line 268) | def cookies(self, all_domains: bool = False, all_info: bool = False) -...
    method close (line 276) | def close(self, others: bool = False) -> None:
    method _find_elements (line 283) | def _find_elements(self,

FILE: DrissionPage/_pages/session_page.py
  class SessionPage (line 25) | class SessionPage(BasePage):
    method __init__ (line 26) | def __init__(self, session_or_options=None, timeout=None):
    method __repr__ (line 40) | def __repr__(self):
    method _s_set_runtime_settings (line 43) | def _s_set_runtime_settings(self):
    method __call__ (line 49) | def __call__(self, locator, index=1, timeout=None):
    method title (line 54) | def title(self):
    method url (line 59) | def url(self):
    method _session_url (line 63) | def _session_url(self):
    method raw_data (line 67) | def raw_data(self):
    method html (line 71) | def html(self):
    method json (line 75) | def json(self):
    method user_agent (line 82) | def user_agent(self):
    method session (line 86) | def session(self):
    method response (line 90) | def response(self):
    method encoding (line 94) | def encoding(self):
    method set (line 98) | def set(self):
    method timeout (line 104) | def timeout(self):
    method get (line 107) | def get(self, url, show_errmsg=False, retry=None, interval=None, timeo...
    method post (line 128) | def post(self, url, show_errmsg=False, retry=None, interval=None, **kw...
    method ele (line 139) | def ele(self, locator, index=1, timeout=None):
    method eles (line 142) | def eles(self, locator, timeout=None):
    method s_ele (line 145) | def s_ele(self, locator=None, index=1):
    method s_eles (line 148) | def s_eles(self, locator):
    method _find_elements (line 151) | def _find_elements(self, locator, timeout, index=1, relative=True, rai...
    method cookies (line 154) | def cookies(self, all_domains=False, all_info=False):
    method close (line 178) | def close(self):
    method _s_connect (line 183) | def _s_connect(self, url, mode, show_errmsg=False, retry=None, interva...
    method _make_response (line 201) | def _make_response(self, url, mode='get', retry=None, interval=None, s...
  function check_headers (line 271) | def check_headers(kwargs, headers, arg):
  function set_charset (line 275) | def set_charset(response):

FILE: DrissionPage/_pages/session_page.pyi
  class SessionPage (line 22) | class SessionPage(BasePage):
    method __init__ (line 35) | def __init__(self, session_or_options: Union[Session, SessionOptions] ...
    method _s_set_runtime_settings (line 41) | def _s_set_runtime_settings(self) -> None:
    method __call__ (line 45) | def __call__(self,
    method title (line 59) | def title(self) -> str:
    method url (line 64) | def url(self) -> str:
    method _session_url (line 69) | def _session_url(self) -> str:
    method raw_data (line 74) | def raw_data(self) -> Union[str, bytes]:
    method html (line 79) | def html(self) -> str:
    method json (line 84) | def json(self) -> Union[dict, None]:
    method user_agent (line 89) | def user_agent(self) -> str:
    method session (line 94) | def session(self) -> Session:
    method response (line 99) | def response(self) -> Response:
    method encoding (line 104) | def encoding(self) -> str:
    method set (line 109) | def set(self) -> SessionPageSetter:
    method timeout (line 114) | def timeout(self) -> float:
    method get (line 118) | def get(self,
    method post (line 160) | def post(self,
    method ele (line 202) | def ele(self,
    method eles (line 214) | def eles(self,
    method s_ele (line 224) | def s_ele(self,
    method s_eles (line 234) | def s_eles(self, locator: Union[Tuple[str, str], str]) -> SessionEleme...
    method _find_elements (line 241) | def _find_elements(self,
    method cookies (line 256) | def cookies(self,
    method close (line 266) | def close(self) -> None:
    method _s_connect (line 270) | def _s_connect(self,
    method _make_response (line 288) | def _make_response(self,
  function check_headers (line 305) | def check_headers(kwargs: Union[dict, CaseInsensitiveDict],
  function set_charset (line 317) | def set_charset(response: Response) -> Response:

FILE: DrissionPage/_pages/web_page.py
  class WebPage (line 18) | class WebPage(SessionPage, ChromiumPage, BasePage):
    method __new__ (line 19) | def __new__(cls, mode='d', timeout=None, chromium_options=None, sessio...
    method __init__ (line 23) | def __init__(self, mode='d', timeout=None, chromium_options=None, sess...
    method __call__ (line 43) | def __call__(self, locator, index=1, timeout=None):
    method __repr__ (line 48) | def __repr__(self):
    method latest_tab (line 52) | def latest_tab(self):
    method set (line 56) | def set(self):
    method url (line 62) | def url(self):
    method _browser_url (line 66) | def _browser_url(self):
    method title (line 70) | def title(self):
    method raw_data (line 74) | def raw_data(self):
    method html (line 80) | def html(self):
    method json (line 86) | def json(self):
    method response (line 90) | def response(self):
    method mode (line 94) | def mode(self):
    method user_agent (line 98) | def user_agent(self):
    method session (line 102) | def session(self):
    method _session_url (line 108) | def _session_url(self):
    method timeout (line 112) | def timeout(self):
    method download_path (line 116) | def download_path(self):
    method get (line 119) | def get(self, url, show_errmsg=False, retry=None, interval=None, timeo...
    method post (line 127) | def post(self, url, show_errmsg=False, retry=None, interval=None, **kw...
    method ele (line 133) | def ele(self, locator, index=1, timeout=None):
    method eles (line 137) | def eles(self, locator, timeout=None):
    method s_ele (line 140) | def s_ele(self, locator=None, index=1, timeout=None):
    method s_eles (line 144) | def s_eles(self, locator, timeout=None):
    method change_mode (line 148) | def change_mode(self, mode=None, go=True, copy_cookies=True):
    method cookies_to_session (line 182) | def cookies_to_session(self, copy_user_agent=True):
    method cookies_to_browser (line 192) | def cookies_to_browser(self):
    method cookies (line 197) | def cookies(self, all_domains=False, all_info=False):
    method get_tab (line 201) | def get_tab(self, id_or_num=None, title=None, url=None, tab_type='page...
    method get_tabs (line 205) | def get_tabs(self, title=None, url=None, tab_type='page', as_id=False):
    method new_tab (line 208) | def new_tab(self, url=None, new_window=False, background=False, new_co...
    method close_driver (line 211) | def close_driver(self):
    method close_session (line 222) | def close_session(self):
    method close (line 232) | def close(self):
    method _find_elements (line 240) | def _find_elements(self, locator, timeout, index=1, relative=False, ra...
    method quit (line 245) | def quit(self, timeout=5, force=True, del_data=False):
    method _set_session_options (line 256) | def _set_session_options(self, session_or_options=None):

FILE: DrissionPage/_pages/web_page.pyi
  class WebPage (line 28) | class WebPage(SessionPage, ChromiumPage, BasePage):
    method __init__ (line 37) | def __init__(self,
    method __call__ (line 48) | def __call__(self,
    method latest_tab (line 61) | def latest_tab(self) -> Union[MixTab, WebPage, str]:
    method set (line 67) | def set(self) -> WebPageSetter:
    method wait (line 72) | def wait(self) -> WebPageWaiter:
    method url (line 77) | def url(self) -> Union[str, None]:
    method _browser_url (line 82) | def _browser_url(self) -> Union[str, None]:
    method title (line 87) | def title(self) -> str:
    method raw_data (line 92) | def raw_data(self) -> Union[str, bytes]:
    method html (line 97) | def html(self) -> str:
    method json (line 102) | def json(self) -> dict:
    method response (line 107) | def response(self) -> Response:
    method mode (line 112) | def mode(self) -> Literal['s', 'd']:
    method user_agent (line 117) | def user_agent(self) -> str:
    method session (line 122) | def session(self) -> Session:
    method _session_url (line 127) | def _session_url(self) -> str:
    method timeout (line 132) | def timeout(self) -> float:
    method get (line 136) | def get(self,
    method post (line 178) | def post(self,
    method ele (line 220) | def ele(self,
    method eles (line 232) | def eles(self,
    method s_ele (line 242) | def s_ele(self,
    method s_eles (line 254) | def s_eles(self, locator: Union[Tuple[str, str], str], timeout: float ...
    method change_mode (line 262) | def change_mode(self,
    method cookies_to_session (line 276) | def cookies_to_session(self, copy_user_agent: bool = True) -> None:
    method cookies_to_browser (line 283) | def cookies_to_browser(self) -> None:
    method cookies (line 287) | def cookies(self,
    method get_tab (line 297) | def get_tab(self,
    method get_tabs (line 313) | def get_tabs(self,
    method new_tab (line 327) | def new_tab(self,
    method close_driver (line 341) | def close_driver(self) -> None:
    method close_session (line 345) | def close_session(self) -> None:
    method close (line 349) | def close(self) -> None:
    method _find_elements (line 353) | def _find_elements(self,
    method quit (line 370) | def quit(self,

FILE: DrissionPage/_units/actions.py
  class Actions (line 16) | class Actions:
    method __init__ (line 18) | def __init__(self, owner):
    method move_to (line 26) | def move_to(self, ele_or_loc, offset_x=None, offset_y=None, duration=.5):
    method move (line 66) | def move(self, offset_x=0, offset_y=0, duration=.5):
    method click (line 86) | def click(self, on_ele=None, times=1):
    method r_click (line 90) | def r_click(self, on_ele=None, times=1):
    method m_click (line 94) | def m_click(self, on_ele=None, times=1):
    method hold (line 98) | def hold(self, on_ele=None):
    method release (line 102) | def release(self, on_ele=None):
    method r_hold (line 108) | def r_hold(self, on_ele=None):
    method r_release (line 112) | def r_release(self, on_ele=None):
    method m_hold (line 118) | def m_hold(self, on_ele=None):
    method m_release (line 122) | def m_release(self, on_ele=None):
    method _hold (line 128) | def _hold(self, on_ele=None, button='left', count=1):
    method _release (line 136) | def _release(self, button):
    method scroll (line 142) | def scroll(self, delta_y=0, delta_x=0, on_ele=None):
    method up (line 149) | def up(self, pixel):
    method down (line 152) | def down(self, pixel):
    method left (line 155) | def left(self, pixel):
    method right (line 158) | def right(self, pixel):
    method key_down (line 161) | def key_down(self, key):
    method key_up (line 173) | def key_up(self, key):
    method type (line 185) | def type(self, keys, interval=0):
    method input (line 209) | def input(self, text):
    method drag_in (line 213) | def drag_in(self, ele_or_loc, files=None, text=None, title=None, baseU...
    method wait (line 247) | def wait(self, second, scope=None):
  function location_to_client (line 252) | def location_to_client(page, lx, ly):

FILE: DrissionPage/_units/actions.pyi
  class Actions (line 45) | class Actions:
    method __init__ (line 55) | def __init__(self, owner: ChromiumBase):
    method move_to (line 61) | def move_to(self, ele_or_loc: Union[ChromiumElement, Tuple[float, floa...
    method move (line 73) | def move(self, offset_x: float = 0, offset_y: float = 0, duration: flo...
    method click (line 82) | def click(self, on_ele: Union[ChromiumElement, str] = None, times: int...
    method r_click (line 90) | def r_click(self, on_ele: Union[ChromiumElement, str] = None, times: i...
    method m_click (line 98) | def m_click(self, on_ele: Union[ChromiumElement, str] = None, times: i...
    method hold (line 106) | def hold(self, on_ele: Union[ChromiumElement, str] = None) -> Actions:
    method release (line 113) | def release(self, on_ele: Union[ChromiumElement, str] = None) -> Actions:
    method r_hold (line 120) | def r_hold(self, on_ele: Union[ChromiumElement, str] = None) -> Actions:
    method r_release (line 127) | def r_release(self, on_ele: Union[ChromiumElement, str] = None) -> Act...
    method m_hold (line 134) | def m_hold(self, on_ele: Union[ChromiumElement, str] = None) -> Actions:
    method m_release (line 141) | def m_release(self, on_ele: Union[ChromiumElement, str] = None) -> Act...
    method _hold (line 148) | def _hold(self,
    method _release (line 160) | def _release(self, button: str) -> Actions:
    method scroll (line 167) | def scroll(self, delta_y: int = 0, delta_x: int = 0,
    method up (line 177) | def up(self, pixel: int) -> Actions:
    method down (line 184) | def down(self, pixel: int) -> Actions:
    method left (line 191) | def left(self, pixel: int) -> Actions:
    method right (line 198) | def right(self, pixel: int) -> Actions:
    method key_down (line 205) | def key_down(self, key: Union[KEYS, str]) -> Actions:
    method key_up (line 212) | def key_up(self, key: Union[KEYS, str]) -> Actions:
    method type (line 219) | def type(self,
    method input (line 229) | def input(self, text: Any) -> Actions:
    method drag_in (line 236) | def drag_in(self, ele_or_loc: Union[str, ChromiumElement], files: Unio...
    method wait (line 248) | def wait(self, second: float, scope: float = None) -> Actions:
  function location_to_client (line 257) | def location_to_client(page: ChromiumBase, lx: int, ly: int) -> tuple:

FILE: DrissionPage/_units/clicker.py
  class Clicker (line 18) | class Clicker(object):
    method __init__ (line 19) | def __init__(self, ele):
    method __call__ (line 22) | def __call__(self, by_js=False, timeout=1.5, wait_stop=True):
    method left (line 25) | def left(self, by_js=False, timeout=1.5, wait_stop=True):
    method right (line 98) | def right(self):
    method middle (line 102) | def middle(self, get_tab=True):
    method at (line 112) | def at(self, offset_x=None, offset_y=None, button='left', count=1):
    method multi (line 120) | def multi(self, times=2):
    method to_download (line 123) | def to_download(self, save_path=None, rename=None, suffix=None, new_ta...
    method to_upload (line 177) | def to_upload(self, file_paths, by_js=False):
    method for_new_tab (line 182) | def for_new_tab(self, by_js=False, timeout=3):
    method for_url_change (line 190) | def for_url_change(self, text=None, exclude=False, by_js=False, timeou...
    method for_title_change (line 197) | def for_title_change(self, text=None, exclude=False, by_js=False, time...
    method _click (line 204) | def _click(self, view_x, view_y, button='left', count=1):

FILE: DrissionPage/_units/clicker.pyi
  class Clicker (line 17) | class Clicker(object):
    method __init__ (line 20) | def __init__(self, ele: ChromiumElement):
    method __call__ (line 26) | def __call__(self, by_js: Union[bool, str, None] = False,
    method left (line 37) | def left(self, by_js: Union[bool, str, None] = False,
    method right (line 47) | def right(self) -> ChromiumElement:
    method middle (line 51) | def middle(self, get_tab: bool = True) -> Union[ChromiumTab, MixTab, N...
    method at (line 58) | def at(self,
    method multi (line 72) | def multi(self, times: int = 2) -> ChromiumElement:
    method to_download (line 79) | def to_download(self,
    method to_upload (line 97) | def to_upload(self, file_paths: Union[str, Path, list, tuple], by_js: ...
    method for_new_tab (line 105) | def for_new_tab(self, by_js: bool = False, timeout: float = 3) -> Unio...
    method for_url_change (line 113) | def for_url_change(self, text: str = None, exclude: bool = False,
    method for_title_change (line 124) | def for_title_change(self, text: str = None, exclude: bool = False,
    method _click (line 135) | def _click(self,

FILE: DrissionPage/_units/console.py
  class Console (line 14) | class Console(object):
    method __init__ (line 15) | def __init__(self, owner):
    method messages (line 22) | def messages(self):
    method start (line 30) | def start(self):
    method stop (line 38) | def stop(self):
    method clear (line 43) | def clear(self):
    method wait (line 46) | def wait(self, timeout=None):
    method steps (line 62) | def steps(self, timeout=None):
    method _console (line 78) | def _console(self, **kwargs):
  class ConsoleData (line 82) | class ConsoleData(object):
    method __init__ (line 85) | def __init__(self, data):
    method __getattr__ (line 88) | def __getattr__(self, item):
    method __repr__ (line 91) | def __repr__(self):
    method body (line 96) | def body(self):

FILE: DrissionPage/_units/console.pyi
  class Console (line 14) | class Console(object):
    method __init__ (line 20) | def __init__(self, owner: ChromiumBase) -> None:
    method messages (line 27) | def messages(self) -> List[ConsoleData]:
    method start (line 31) | def start(self) -> None:
    method stop (line 35) | def stop(self) -> None:
    method clear (line 39) | def clear(self) -> None:
    method wait (line 43) | def wait(self, timeout: float = None) -> Union[ConsoleData, False]:
    method steps (line 50) | def steps(self, timeout: Optional[float] = None) -> Iterable[ConsoleDa...
    method _console (line 57) | def _console(self, **kwargs) -> None: ...
  class ConsoleData (line 60) | class ConsoleData(object):
    method __init__ (line 63) | def __init__(self, data: dict) -> None: ...
    method __getattr__ (line 65) | def __getattr__(self, item: str) -> str: ...
    method body (line 68) | def body(self) -> Any: ...

FILE: DrissionPage/_units/cookies_setter.py
  class BrowserCookiesSetter (line 12) | class BrowserCookiesSetter(object):
    method __init__ (line 13) | def __init__(self, owner):
    method __call__ (line 16) | def __call__(self, cookies):
    method clear (line 19) | def clear(self):
  class CookiesSetter (line 23) | class CookiesSetter(BrowserCookiesSetter):
    method __call__ (line 24) | def __call__(self, cookies):
    method remove (line 27) | def remove(self, name, url=None, domain=None, path=None):
    method clear (line 41) | def clear(self):
  class SessionCookiesSetter (line 45) | class SessionCookiesSetter(object):
    method __init__ (line 46) | def __init__(self, owner):
    method __call__ (line 49) | def __call__(self, cookies):
    method remove (line 52) | def remove(self, name):
    method clear (line 55) | def clear(self):
  class WebPageCookiesSetter (line 59) | class WebPageCookiesSetter(CookiesSetter):
    method __call__ (line 60) | def __call__(self, cookies):
    method remove (line 66) | def remove(self, name, url=None, domain=None, path=None):
    method clear (line 74) | def clear(self):
  class MixTabCookiesSetter (line 81) | class MixTabCookiesSetter(CookiesSetter):
    method __call__ (line 82) | def __call__(self, cookies):
    method remove (line 88) | def remove(self, name, url=None, domain=None, path=None):
    method clear (line 96) | def clear(self):

FILE: DrissionPage/_units/cookies_setter.pyi
  class BrowserCookiesSetter (line 18) | class BrowserCookiesSetter(object):
    method __init__ (line 21) | def __init__(self, owner: Chromium):
    method __call__ (line 27) | def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str,...
    method clear (line 34) | def clear(self) -> None:
  class CookiesSetter (line 39) | class CookiesSetter(BrowserCookiesSetter):
    method __init__ (line 42) | def __init__(self, owner: ChromiumBase):
    method __call__ (line 48) | def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str,...
    method remove (line 55) | def remove(self,
    method clear (line 69) | def clear(self) -> None:
  class SessionCookiesSetter (line 74) | class SessionCookiesSetter(object):
    method __init__ (line 77) | def __init__(self, owner: SessionPage):
    method __call__ (line 83) | def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str,...
    method remove (line 90) | def remove(self, name: str) -> None:
    method clear (line 97) | def clear(self) -> None:
  class WebPageCookiesSetter (line 102) | class WebPageCookiesSetter(CookiesSetter, SessionCookiesSetter):
    method __init__ (line 105) | def __init__(self, owner: WebPage):
    method __call__ (line 111) | def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str,...
    method remove (line 118) | def remove(self,
    method clear (line 132) | def clear(self) -> None:
  class MixTabCookiesSetter (line 137) | class MixTabCookiesSetter(CookiesSetter, SessionCookiesSetter):
    method __init__ (line 140) | def __init__(self, owner: MixTab):
    method __call__ (line 146) | def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str,...
    method remove (line 153) | def remove(self,
    method clear (line 167) | def clear(self) -> None:

FILE: DrissionPage/_units/downloader.py
  class DownloadManager (line 18) | class DownloadManager(object):
    method __init__ (line 20) | def __init__(self, browser):
    method missions (line 39) | def missions(self):
    method set_path (line 42) | def set_path(self, tab, path):
    method set_rename (line 56) | def set_rename(tab_id, rename=None, suffix=None):
    method set_file_exists (line 62) | def set_file_exists(tab_id, mode):
    method set_flag (line 65) | def set_flag(self, tab_id, flag):
    method get_flag (line 68) | def get_flag(self, tab_id):
    method get_tab_missions (line 71) | def get_tab_missions(self, tab_id):
    method set_done (line 74) | def set_done(self, mission, state, final_path=None):
    method cancel (line 86) | def cancel(self, mission):
    method skip (line 95) | def skip(self, mission):
    method clear_tab_info (line 102) | def clear_tab_info(self, tab_id):
    method _onDownloadWillBegin (line 108) | def _onDownloadWillBegin(self, **kwargs):
    method _onDownloadProgress (line 170) | def _onDownloadProgress(self, **kwargs):
  class TabDownloadSettings (line 207) | class TabDownloadSettings(object):
    method __new__ (line 210) | def __new__(cls, tab_id):
    method __init__ (line 218) | def __init__(self, tab_id):
  class DownloadMission (line 231) | class DownloadMission(object):
    method __init__ (line 232) | def __init__(self, mgr, tab_id, _id, folder, name, url, tmp_path, over...
    method __repr__ (line 248) | def __repr__(self):
    method rate (line 252) | def rate(self):
    method is_done (line 256) | def is_done(self):
    method cancel (line 259) | def cancel(self):
    method wait (line 262) | def wait(self, show=True, timeout=None, cancel_if_timeout=True):

FILE: DrissionPage/_units/downloader.pyi
  class DownloadManager (line 16) | class DownloadManager(object):
    method __init__ (line 26) | def __init__(self, browser: Chromium):
    method missions (line 33) | def missions(self) -> Dict[str, DownloadMission]:
    method set_path (line 37) | def set_path(self, tab: Union[str, ChromiumBase], path: str) -> None:
    method set_rename (line 46) | def set_rename(tab_id: str,
    method set_file_exists (line 58) | def set_file_exists(tab_id: str, mode: FILE_EXISTS) -> None:
    method set_flag (line 66) | def set_flag(self, tab_id: str, flag: Union[bool, DownloadMission, Non...
    method get_flag (line 74) | def get_flag(self, tab_id: str) -> Union[bool, DownloadMission, None]:
    method get_tab_missions (line 81) | def get_tab_missions(self, tab_id: str) -> list:
    method set_done (line 88) | def set_done(self,
    method cancel (line 100) | def cancel(self, mission: DownloadMission) -> None:
    method skip (line 107) | def skip(self, mission: DownloadMission) -> None:
    method clear_tab_info (line 114) | def clear_tab_info(self, tab_id: str) -> None:
    method _onDownloadWillBegin (line 121) | def _onDownloadWillBegin(self, **kwargs) -> None:
    method _onDownloadProgress (line 125) | def _onDownloadProgress(self, **kwargs) -> None:
  class TabDownloadSettings (line 130) | class TabDownloadSettings(object):
    method __init__ (line 139) | def __init__(self, tab_id: str):
  class DownloadMission (line 146) | class DownloadMission(object):
    method __init__ (line 162) | def __init__(self,
    method rate (line 184) | def rate(self) -> float:
    method is_done (line 189) | def is_done(self) -> bool:
    method cancel (line 193) | def cancel(self) -> None:
    method wait (line 197) | def wait(self,

FILE: DrissionPage/_units/listener.py
  class Listener (line 21) | class Listener(object):
    method __init__ (line 24) | def __init__(self, owner):
    method targets (line 45) | def targets(self):
    method set_targets (line 49) | def set_targets(self, targets=True, is_regex=False, method=('GET', 'PO...
    method start (line 84) | def start(self, targets=None, is_regex=None, method=None, res_type=None):
    method wait (line 102) | def wait(self, count=1, timeout=None, fit_count=True, raise_err=None):
    method steps (line 135) | def steps(self, count=None, timeout=None, gap=1):
    method stop (line 162) | def stop(self):
    method pause (line 169) | def pause(self, clear=True):
    method resume (line 179) | def resume(self):
    method clear (line 185) | def clear(self):
    method wait_silent (line 192) | def wait_silent(self, timeout=None, targets_only=False, limit=0):
    method _to_target (line 210) | def _to_target(self, target_id, address, owner):
    method _set_callback (line 223) | def _set_callback(self):
    method _requestWillBeSent (line 231) | def _requestWillBeSent(self, **kwargs):
    method _requestWillBeSentExtraInfo (line 259) | def _requestWillBeSentExtraInfo(self, **kwargs):
    method _response_received (line 263) | def _response_received(self, **kwargs):
    method _responseReceivedExtraInfo (line 269) | def _responseReceivedExtraInfo(self, **kwargs):
    method _loading_finished (line 283) | def _loading_finished(self, **kwargs):
    method _loading_failed (line 318) | def _loading_failed(self, **kwargs):
  class FrameListener (line 346) | class FrameListener(Listener):
    method _requestWillBeSent (line 347) | def _requestWillBeSent(self, **kwargs):
    method _response_received (line 352) | def _response_received(self, **kwargs):
  class DataPacket (line 358) | class DataPacket(object):
    method __init__ (line 360) | def __init__(self, tab_id, target):
    method __repr__ (line 380) | def __repr__(self):
    method _request_extra_info (line 385) | def _request_extra_info(self):
    method _response_extra_info (line 389) | def _response_extra_info(self):
    method url (line 393) | def url(self):
    method method (line 397) | def method(self):
    method frameId (line 401) | def frameId(self):
    method resourceType (line 405) | def resourceType(self):
    method request (line 409) | def request(self):
    method response (line 415) | def response(self):
    method fail_info (line 421) | def fail_info(self):
    method wait_extra_info (line 426) | def wait_extra_info(self, timeout=None):
  class Request (line 442) | class Request(object):
    method __init__ (line 443) | def __init__(self, data_packet, raw_request, post_data):
    method __getattr__ (line 450) | def __getattr__(self, item):
    method headers (line 454) | def headers(self):
    method params (line 465) | def params(self):
    method postData (line 470) | def postData(self):
    method cookies (line 485) | def cookies(self):
    method extra_info (line 489) | def extra_info(self):
  class Response (line 493) | class Response(object):
    method __init__ (line 494) | def __init__(self, data_packet, raw_response, raw_body, base64_body):
    method __getattr__ (line 502) | def __getattr__(self, item):
    method headers (line 506) | def headers(self):
    method raw_body (line 517) | def raw_body(self):
    method body (line 521) | def body(self):
    method extra_info (line 535) | def extra_info(self):
  class ExtraInfo (line 539) | class ExtraInfo(object):
    method __init__ (line 540) | def __init__(self, extra_info):
    method all_info (line 544) | def all_info(self):
    method __getattr__ (line 547) | def __getattr__(self, item):
  class RequestExtraInfo (line 551) | class RequestExtraInfo(ExtraInfo):
  class ResponseExtraInfo (line 555) | class ResponseExtraInfo(ExtraInfo):
  class FailInfo (line 559) | class FailInfo(object):
    method __init__ (line 560) | def __init__(self, data_packet, fail_info):
    method __getattr__ (line 564) | def __getattr__(self, item):

FILE: DrissionPage/_units/listener.pyi
  class Listener (line 21) | class Listener(object):
    method __init__ (line 37) | def __init__(self, owner: ChromiumBase):
    method targets (line 44) | def targets(self) -> Optional[set]: ...
    method set_targets (line 46) | def set_targets(self,
    method start (line 62) | def start(self,
    method wait (line 78) | def wait(self,
    method steps (line 92) | def steps(self,
    method stop (line 104) | def stop(self) -> None:
    method pause (line 108) | def pause(self, clear: bool = True) -> None:
    method resume (line 115) | def resume(self) -> None:
    method clear (line 119) | def clear(self) -> None:
    method wait_silent (line 123) | def wait_silent(self,
    method _to_target (line 135) | def _to_target(self, target_id: str, address: str, owner: ChromiumBase...
    method _set_callback (line 144) | def _set_callback(self) -> None: ...
    method _requestWillBeSent (line 146) | def _requestWillBeSent(self, **kwargs) -> None: ...
    method _requestWillBeSentExtraInfo (line 148) | def _requestWillBeSentExtraInfo(self, **kwargs) -> None: ...
    method _response_received (line 150) | def _response_received(self, **kwargs) -> None: ...
    method _responseReceivedExtraInfo (line 152) | def _responseReceivedExtraInfo(self, **kwargs) -> None: ...
    method _loading_finished (line 154) | def _loading_finished(self, **kwargs) -> None: ...
    method _loading_failed (line 156) | def _loading_failed(self, **kwargs) -> None: ...
  class FrameListener (line 159) | class FrameListener(Listener):
    method __init__ (line 163) | def __init__(self, owner: ChromiumFrame):
  class DataPacket (line 170) | class DataPacket(object):
    method __init__ (line 189) | def __init__(self, tab_id: str, target: [str, bool]):
    method url (line 197) | def url(self) -> str:
    method method (line 202) | def method(self) -> str:
    method frameId (line 207) | def frameId(self) -> str:
    method resourceType (line 212) | def resourceType(self) -> str:
    method request (line 217) | def request(self) -> Request:
    method response (line 222) | def response(self) -> Response:
    method fail_info (line 227) | def fail_info(self) -> Optional[FailInfo]:
    method wait_extra_info (line 231) | def wait_extra_info(self, timeout: float = None) -> bool:
    method _request_extra_info (line 239) | def _request_extra_info(self) -> Optional[dict]: ...
    method _response_extra_info (line 242) | def _response_extra_info(self) -> Optional[dict]: ...
  class Request (line 245) | class Request(object):
    method __init__ (line 266) | def __init__(self,
    method headers (line 278) | def headers(self) -> dict:
    method params (line 283) | def params(self) -> dict:
    method postData (line 288) | def postData(self) -> Any:
    method cookies (line 293) | def cookies(self) -> List[dict]:
    method extra_info (line 298) | def extra_info(self) -> Optional[RequestExtraInfo]:
  class Response (line 303) | class Response(object):
    method __init__ (line 338) | def __init__(self,
    method headers (line 352) | def headers(self) -> CaseInsensitiveDict:
    method raw_body (line 357) | def raw_body(self) -> str:
    method body (line 362) | def body(self) -> Any:
    method extra_info (line 367) | def extra_info(self) -> Optional[ResponseExtraInfo]:
  class ExtraInfo (line 372) | class ExtraInfo(object):
    method __init__ (line 375) | def __init__(self, extra_info: dict):
    method all_info (line 382) | def all_info(self) -> dict:
  class RequestExtraInfo (line 387) | class RequestExtraInfo(ExtraInfo):
  class ResponseExtraInfo (line 396) | class ResponseExtraInfo(ExtraInfo):
  class FailInfo (line 407) | class FailInfo(object):
    method __init__ (line 415) | def __init__(self, data_packet: DataPacket, fail_info: dict):

FILE: DrissionPage/_units/rect.py
  class ElementRect (line 10) | class ElementRect(object):
    method __init__ (line 11) | def __init__(self, ele):
    method corners (line 15) | def corners(self):
    method viewport_corners (line 23) | def viewport_corners(self):
    method size (line 28) | def size(self):
    method location (line 34) | def location(self):
    method midpoint (line 38) | def midpoint(self):
    method click_point (line 42) | def click_point(self):
    method viewport_location (line 46) | def viewport_location(self):
    method viewport_midpoint (line 51) | def viewport_midpoint(self):
    method viewport_click_point (line 56) | def viewport_click_point(self):
    method screen_location (line 61) | def screen_location(self):
    method screen_midpoint (line 72) | def screen_midpoint(self):
    method screen_click_point (line 83) | def screen_click_point(self):
    method scroll_position (line 94) | def scroll_position(self):
    method _get_viewport_rect (line 99) | def _get_viewport_rect(self, quad):
    method _get_page_coord (line 102) | def _get_page_coord(self, x, y):
  class TabRect (line 109) | class TabRect(object):
    method __init__ (line 110) | def __init__(self, owner):
    method window_state (line 114) | def window_state(self):
    method window_location (line 118) | def window_location(self):
    method window_size (line 125) | def window_size(self):
    method page_location (line 135) | def page_location(self):
    method viewport_location (line 141) | def viewport_location(self):
    method size (line 148) | def size(self):
    method viewport_size (line 153) | def viewport_size(self):
    method viewport_size_with_scrollbar (line 158) | def viewport_size_with_scrollbar(self):
    method scroll_position (line 164) | def scroll_position(self):
    method _get_page_rect (line 168) | def _get_page_rect(self):
    method _get_window_rect (line 171) | def _get_window_rect(self):
  class FrameRect (line 175) | class FrameRect(object):
    method __init__ (line 178) | def __init__(self, frame):
    method location (line 182) | def location(self):
    method viewport_location (line 186) | def viewport_location(self):
    method screen_location (line 190) | def screen_location(self):
    method size (line 194) | def size(self):
    method viewport_size (line 200) | def viewport_size(self):
    method corners (line 204) | def corners(self):
    method viewport_corners (line 208) | def viewport_corners(self):
    method scroll_position (line 212) | def scroll_position(self):

FILE: DrissionPage/_units/rect.pyi
  class ElementRect (line 19) | class ElementRect(object):
    method __init__ (line 21) | def __init__(self, ele: ChromiumElement):
    method corners (line 28) | def corners(self) -> Tuple[Tuple[float, float], ...]:
    method viewport_corners (line 33) | def viewport_corners(self) -> Tuple[Tuple[float, float], ...]:
    method size (line 38) | def size(self) -> Tuple[float, float]:
    method location (line 43) | def location(self) -> Tuple[float, float]:
    method midpoint (line 48) | def midpoint(self) -> Tuple[float, float]:
    method click_point (line 53) | def click_point(self) -> Tuple[float, float]:
    method viewport_location (line 58) | def viewport_location(self) -> Tuple[float, float]:
    method viewport_midpoint (line 63) | def viewport_midpoint(self) -> Tuple[float, float]:
    method viewport_click_point (line 68) | def viewport_click_point(self) -> Tuple[float, float]:
    method screen_location (line 73) | def screen_location(self) -> Tuple[float, float]:
    method screen_midpoint (line 78) | def screen_midpoint(self) -> Tuple[float, float]:
    method screen_click_point (line 83) | def screen_click_point(self) -> Tuple[float, float]:
    method scroll_position (line 88) | def scroll_position(self) -> Tuple[float, float]:
    method _get_viewport_rect (line 92) | def _get_viewport_rect(self, quad: str) -> Union[list, None]:
    method _get_page_coord (line 99) | def _get_page_coord(self, x: float, y: float) -> Tuple[float, float]:
  class TabRect (line 108) | class TabRect(object):
    method __init__ (line 109) | def __init__(self, owner: ChromiumBase):
    method window_state (line 116) | def window_state(self) -> str:
    method window_location (line 121) | def window_location(self) -> Tuple[int, int]:
    method window_size (line 126) | def window_size(self) -> Tuple[int, int]:
    method page_location (line 131) | def page_location(self) -> Tuple[int, int]:
    method viewport_location (line 136) | def viewport_location(self) -> Tuple[int, int]:
    method size (line 141) | def size(self) -> Tuple[int, int]:
    method viewport_size (line 146) | def viewport_size(self) -> Tuple[int, int]:
    method viewport_size_with_scrollbar (line 151) | def viewport_size_with_scrollbar(self) -> Tuple[int, int]:
    method scroll_position (line 156) | def scroll_position(self) -> Tuple[int, int]:
    method _get_page_rect (line 160) | def _get_page_rect(self) -> dict:
    method _get_window_rect (line 164) | def _get_window_rect(self) -> dict:
  class FrameRect (line 169) | class FrameRect(object):
    method __init__ (line 172) | def __init__(self, frame: ChromiumFrame):
    method location (line 179) | def location(self) -> Tuple[float, float]:
    method viewport_location (line 184) | def viewport_location(self) -> Tuple[float, float]:
    method screen_location (line 189) | def screen_location(self) -> Tuple[float, float]:
    method size (line 194) | def size(self) -> Tuple[float, float]:
    method viewport_size (line 199) | def viewport_size(self) -> Tuple[float, float]:
    method corners (line 204) | def corners(self) -> Tuple[Tuple[float, float], ...]:
    method viewport_corners (line 209) | def viewport_corners(self) -> Tuple[Tuple[float, float], ...]:
    method scroll_position (line 214) | def scroll_position(self) -> Tuple[float, float]:

FILE: DrissionPage/_units/screencast.py
  class Screencast (line 20) | class Screencast(object):
    method __init__ (line 21) | def __init__(self, owner):
    method set_mode (line 30) | def set_mode(self):
    method start (line 33) | def start(self, save_path=None):
    method stop (line 83) | def stop(self, video_name=None, suffix='mp4', coding='mp4v'):
    method set_save_path (line 139) | def set_save_path(self, save_path=None):
    method _run (line 147) | def _run(self):
    method _onScreencastFrame (line 155) | def _onScreencastFrame(self, **kwargs):
  class ScreencastMode (line 162) | class ScreencastMode(object):
    method __init__ (line 163) | def __init__(self, screencast):
    method video_mode (line 166) | def video_mode(self):
    method frugal_video_mode (line 169) | def frugal_video_mode(self):
    method js_video_mode (line 172) | def js_video_mode(self):
    method frugal_imgs_mode (line 175) | def frugal_imgs_mode(self):
    method imgs_mode (line 178) | def imgs_mode(self):

FILE: DrissionPage/_units/screencast.pyi
  class Screencast (line 14) | class Screencast(object):
    method __init__ (line 22) | def __init__(self, owner: ChromiumBase):
    method set_mode (line 28) | def set_mode(self) -> ScreencastMode:
    method start (line 32) | def start(self, save_path: Union[str, Path] = None) -> None:
    method stop (line 39) | def stop(self, video_name: str = None, suffix: str='mp4', coding:str='...
    method set_save_path (line 48) | def set_save_path(self, save_path: Union[str, Path] = None) -> None:
    method _run (line 55) | def _run(self) -> None:
    method _onScreencastFrame (line 59) | def _onScreencastFrame(self, **kwargs) -> None:
  class ScreencastMode (line 64) | class ScreencastMode(object):
    method __init__ (line 67) | def __init__(self, screencast: Screencast):
    method video_mode (line 73) | def video_mode(self) -> None:
    method frugal_video_mode (line 77) | def frugal_video_mode(self) -> None:
    method js_video_mode (line 81) | def js_video_mode(self) -> None:
    method frugal_imgs_mode (line 85) | def frugal_imgs_mode(self) -> None:
    method imgs_mode (line 89) | def imgs_mode(self) -> None:

FILE: DrissionPage/_units/scroller.py
  class Scroller (line 11) | class Scroller(object):
    method __init__ (line 14) | def __init__(self, owner):
    method __call__ (line 19) | def __call__(self, pixel=300):
    method _run_js (line 22) | def _run_js(self, js):
    method to_top (line 27) | def to_top(self):
    method to_bottom (line 31) | def to_bottom(self):
    method to_half (line 35) | def to_half(self):
    method to_rightmost (line 39) | def to_rightmost(self):
    method to_leftmost (line 43) | def to_leftmost(self):
    method to_location (line 47) | def to_location(self, x, y):
    method up (line 51) | def up(self, pixel=300):
    method down (line 56) | def down(self, pixel=300):
    method left (line 60) | def left(self, pixel=300):
    method right (line 65) | def right(self, pixel=300):
    method _wait_scrolled (line 69) | def _wait_scrolled(self):
  class ElementScroller (line 92) | class ElementScroller(Scroller):
    method to_see (line 93) | def to_see(self, center=None):
    method to_center (line 97) | def to_center(self):
  class PageScroller (line 102) | class PageScroller(Scroller):
    method __init__ (line 103) | def __init__(self, owner):
    method to_see (line 108) | def to_see(self, loc_or_ele, center=None):
    method _to_see (line 113) | def _to_see(self, ele, center):
  class FrameScroller (line 130) | class FrameScroller(PageScroller):
    method __init__ (line 131) | def __init__(self, owner):
    method to_see (line 138) | def to_see(self, loc_or_ele, center=None):

FILE: DrissionPage/_units/scroller.pyi
  class Scroller (line 19) | class Scroller(object):
    method __init__ (line 25) | def __init__(self, owner: Union[ChromiumBase, ChromiumElement]):
    method __call__ (line 31) | def __call__(self, pixel: int = 300) -> None:
    method to_top (line 38) | def to_top(self) -> None:
    method to_bottom (line 42) | def to_bottom(self) -> None:
    method to_half (line 46) | def to_half(self) -> None:
    method to_rightmost (line 50) | def to_rightmost(self) -> None:
    method to_leftmost (line 54) | def to_leftmost(self) -> None:
    method to_location (line 58) | def to_location(self, x: int, y: int) -> None:
    method up (line 66) | def up(self, pixel: int = 300) -> None:
    method down (line 73) | def down(self, pixel: int = 300) -> None:
    method left (line 80) | def left(self, pixel: int = 300) -> None:
    method right (line 87) | def right(self, pixel: int = 300) -> None:
    method _run_js (line 94) | def _run_js(self, js: str): ...
    method _wait_scrolled (line 96) | def _wait_scrolled(self) -> None:
  class ElementScroller (line 101) | class ElementScroller(Scroller):
    method __init__ (line 104) | def __init__(self, owner: ChromiumElement):
    method to_see (line 110) | def to_see(self, center: Union[bool, None] = None) -> ChromiumElement:
    method to_center (line 117) | def to_center(self) -> ChromiumElement:
    method to_top (line 121) | def to_top(self) -> ChromiumElement:
    method to_bottom (line 125) | def to_bottom(self) -> ChromiumElement:
    method to_half (line 129) | def to_half(self) -> ChromiumElement:
    method to_rightmost (line 133) | def to_rightmost(self) -> ChromiumElement:
    method to_leftmost (line 137) | def to_leftmost(self) -> ChromiumElement:
    method to_location (line 141) | def to_location(self, x: int, y: int) -> ChromiumElement:
    method up (line 149) | def up(self, pixel: int = 300) -> ChromiumElement:
    method down (line 156) | def down(self, pixel: int = 300) -> ChromiumElement:
    method left (line 163) | def left(self, pixel: int = 300) -> ChromiumElement:
    method right (line 170) | def right(self, pixel: int = 300) -> ChromiumElement:
  class PageScroller (line 178) | class PageScroller(Scroller):
    method __init__ (line 181) | def __init__(self, owner: Union[ChromiumBase, ChromiumElement]):
    method to_see (line 187) | def to_see(self,
    method to_top (line 197) | def to_top(self) -> Union[ChromiumTab, MixTab, ChromiumPage, WebPage]:
    method to_bottom (line 201) | def to_bottom(self) -> Union[ChromiumTab, MixTab, ChromiumPage, WebPage]:
    method to_half (line 205) | def to_half(self) -> Union[ChromiumTab, MixTab, ChromiumPage, WebPage]:
    method to_rightmost (line 209) | def to_rightmost(self) -> Union[ChromiumTab, MixTab, ChromiumPage, Web...
    method to_leftmost (line 213) | def to_leftmost(self) -> Union[ChromiumTab, MixTab, ChromiumPage, WebP...
    method to_location (line 217) | def to_location(self, x: int, y: int) -> Union[ChromiumTab, MixTab, Ch...
    method up (line 225) | def up(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, ChromiumP...
    method down (line 232) | def down(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, Chromiu...
    method left (line 239) | def left(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, Chromiu...
    method right (line 246) | def right(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, Chromi...
    method _to_see (line 253) | def _to_see(self, ele: ChromiumElement, center: Union[bool, None]) -> ...
  class FrameScroller (line 262) | class FrameScroller(PageScroller):
    method __init__ (line 265) | def __init__(self, owner: ChromiumFrame): ...
    method to_see (line 267) | def to_see(self,
    method to_top (line 277) | def to_top(self) -> ChromiumFrame:
    method to_bottom (line 281) | def to_bottom(self) -> ChromiumFrame:
    method to_half (line 285) | def to_half(self) -> ChromiumFrame:
    method to_rightmost (line 289) | def to_rightmost(self) -> ChromiumFrame:
    method to_leftmost (line 293) | def to_leftmost(self) -> ChromiumFrame:
    method to_location (line 297) | def to_location(self, x: int, y: int) -> ChromiumFrame:
    method up (line 305) | def up(self, pixel: int = 300) -> ChromiumFrame:
    method down (line 312) | def down(self, pixel: int = 300) -> ChromiumFrame:
    method left (line 319) | def left(self, pixel: int = 300) -> ChromiumFrame:
    method right (line 326) | def right(self, pixel: int = 300) -> ChromiumFrame:

FILE: DrissionPage/_units/selector.py
  class SelectElement (line 13) | class SelectElement(object):
    method __init__ (line 16) | def __init__(self, ele):
    method __call__ (line 21) | def __call__(self, text_or_index, timeout=None):
    method is_multi (line 28) | def is_multi(self):
    method options (line 32) | def options(self):
    method selected_option (line 36) | def selected_option(self):
    method selected_options (line 40) | def selected_options(self):
    method all (line 43) | def all(self):
    method invert (line 48) | def invert(self):
    method clear (line 60) | def clear(self):
    method by_text (line 65) | def by_text(self, text, timeout=None):
    method by_value (line 68) | def by_value(self, value, timeout=None):
    method by_index (line 71) | def by_index(self, index, timeout=None):
    method by_locator (line 74) | def by_locator(self, locator, timeout=None):
    method by_option (line 77) | def by_option(self, option):
    method cancel_by_text (line 80) | def cancel_by_text(self, text, timeout=None):
    method cancel_by_value (line 83) | def cancel_by_value(self, value, timeout=None):
    method cancel_by_index (line 86) | def cancel_by_index(self, index, timeout=None):
    method cancel_by_locator (line 89) | def cancel_by_locator(self, locator, timeout=None):
    method cancel_by_option (line 92) | def cancel_by_option(self, option):
    method _by_loc (line 95) | def _by_loc(self, loc, timeout=None, cancel=False):
    method _select (line 105) | def _select(self, condition, para_type='text', cancel=False, timeout=N...
    method _text_value (line 119) | def _text_value(self, condition, para_type, mode, timeout):
    method _index (line 135) | def _index(self, condition, mode, timeout):
    method _select_options (line 147) | def _select_options(self, option, mode):
    method _dispatch_change (line 159) | def _dispatch_change(self):

FILE: DrissionPage/_units/selector.pyi
  class SelectElement (line 13) | class SelectElement(object):
    method __init__ (line 15) | def __init__(self, ele: ChromiumElement):
    method __call__ (line 21) | def __call__(self,
    method is_multi (line 32) | def is_multi(self) -> bool:
    method options (line 37) | def options(self) -> List[ChromiumElement]:
    method selected_option (line 42) | def selected_option(self) -> Optional[ChromiumElement]:
    method selected_options (line 47) | def selected_options(self) -> List[ChromiumElement]:
    method all (line 51) | def all(self) -> ChromiumElement:
    method invert (line 55) | def invert(self) -> ChromiumElement:
    method clear (line 59) | def clear(self) -> ChromiumElement:
    method by_text (line 63) | def by_text(self,
    method by_value (line 73) | def by_value(self,
    method by_index (line 83) | def by_index(self,
    method by_locator (line 93) | def by_locator(self,
    method by_option (line 103) | def by_option(self,
    method cancel_by_text (line 111) | def cancel_by_text(self,
    method cancel_by_value (line 121) | def cancel_by_value(self,
    method cancel_by_index (line 131) | def cancel_by_index(self,
    method cancel_by_locator (line 141) | def cancel_by_locator(self,
    method cancel_by_option (line 151) | def cancel_by_option(self,
    method _by_loc (line 160) | def _by_loc(self,
    method _select (line 172) | def _select(self,
    method _text_value (line 185) | def _text_value(self,
    method _index (line 199) | def _index(self, condition: set, mode: str, timeout: float) -> Chromiu...
    method _select_options (line 208) | def _select_options(self,
    method _dispatch_change (line 218) | def _dispatch_change(self) -> None:

FILE: DrissionPage/_units/setter.py
  class BaseSetter (line 21) | class BaseSetter(object):
    method __init__ (line 22) | def __init__(self, owner):
    method NoneElement_value (line 25) | def NoneElement_value(self, value=None, on_off=True):
    method retry_times (line 29) | def retry_times(self, times):
    method retry_interval (line 32) | def retry_interval(self, interval):
    method download_path (line 35) | def download_path(self, path):
  class SessionPageSetter (line 41) | class SessionPageSetter(BaseSetter):
    method __init__ (line 42) | def __init__(self, owner):
    method cookies (line 47) | def cookies(self):
    method download_path (line 52) | def download_path(self, path):
    method timeout (line 57) | def timeout(self, second):
    method encoding (line 60) | def encoding(self, encoding, set_all=True):
    method headers (line 66) | def headers(self, headers):
    method header (line 69) | def header(self, name, value):
    method user_agent (line 72) | def user_agent(self, ua):
    method proxies (line 75) | def proxies(self, http=None, https=None):
    method auth (line 78) | def auth(self, auth):
    method hooks (line 81) | def hooks(self, hooks):
    method params (line 84) | def params(self, params):
    method verify (line 87) | def verify(self, on_off):
    method cert (line 90) | def cert(self, cert):
    method stream (line 93) | def stream(self, on_off):
    method trust_env (line 96) | def trust_env(self, on_off):
    method max_redirects (line 99) | def max_redirects(self, times):
    method add_adapter (line 102) | def add_adapter(self, url, adapter):
  class BrowserBaseSetter (line 106) | class BrowserBaseSetter(BaseSetter):
    method __init__ (line 107) | def __init__(self, owner):
    method load_mode (line 112) | def load_mode(self):
    method timeouts (line 115) | def timeouts(self, base=None, page_load=None, script=None):
  class BrowserSetter (line 126) | class BrowserSetter(BrowserBaseSetter):
    method cookies (line 129) | def cookies(self):
    method auto_handle_alert (line 134) | def auto_handle_alert(self, on_off=True, accept=True):
    method download_path (line 137) | def download_path(self, path):
    method download_file_name (line 141) | def download_file_name(self, name=None, suffix=None):
    method when_download_file_exists (line 144) | def when_download_file_exists(self, mode):
  class ChromiumBaseSetter (line 154) | class ChromiumBaseSetter(BrowserBaseSetter):
    method scroll (line 157) | def scroll(self):
    method cookies (line 161) | def cookies(self):
    method headers (line 166) | def headers(self, headers):
    method user_agent (line 170) | def user_agent(self, ua, platform=None):
    method session_storage (line 176) | def session_storage(self, item, value):
    method local_storage (line 187) | def local_storage(self, item, value):
    method upload_files (line 198) | def upload_files(self, files):
    method auto_handle_alert (line 209) | def auto_handle_alert(self, on_off=True, accept=True):
    method blocked_urls (line 212) | def blocked_urls(self, urls):
  class TabSetter (line 224) | class TabSetter(ChromiumBaseSetter):
    method __init__ (line 225) | def __init__(self, owner):
    method window (line 229) | def window(self):
    method download_path (line 232) | def download_path(self, path):
    method download_file_name (line 238) | def download_file_name(self, name=None, suffix=None):
    method when_download_file_exists (line 241) | def when_download_file_exists(self, mode):
    method activate (line 250) | def activate(self):
  class ChromiumPageSetter (line 254) | class ChromiumPageSetter(TabSetter):
    method NoneElement_value (line 256) | def NoneElement_value(self, value=None, on_off=True):
    method retry_times (line 261) | def retry_times(self, times):
    method retry_interval (line 265) | def retry_interval(self, interval):
    method download_path (line 269) | def download_path(self, path):
    method download_file_name (line 277) | def download_file_name(self, name=None, suffix=None):
    method when_download_file_exists (line 280) | def when_download_file_exists(self, mode):
  class WebPageSetter (line 284) | class WebPageSetter(ChromiumPageSetter):
    method __init__ (line 285) | def __init__(self, owner):
    method cookies (line 291) | def cookies(self):
    method headers (line 296) | def headers(self, headers):
    method user_agent (line 302) | def user_agent(self, ua, platform=None):
  class MixTabSetter (line 309) | class MixTabSetter(TabSetter):
    method __init__ (line 310) | def __init__(self, owner):
    method cookies (line 316) | def cookies(self):
    method headers (line 321) | def headers(self, headers):
    method user_agent (line 327) | def user_agent(self, ua, platform=None):
    method timeouts (line 333) | def timeouts(self, base=None, page_load=None, script=None):
  class ChromiumElementSetter (line 339) | class ChromiumElementSetter(object):
    method __init__ (line 340) | def __init__(self, ele):
    method attr (line 343) | def attr(self, name, value=''):
    method property (line 352) | def property(self, name, value):
    method style (line 356) | def style(self, name, value):
    method innerHTML (line 362) | def innerHTML(self, html):
    method value (line 365) | def value(self, value):
  class ChromiumFrameSetter (line 369) | class ChromiumFrameSetter(ChromiumBaseSetter):
    method attr (line 370) | def attr(self, name, value):
    method property (line 373) | def property(self, name, value):
    method style (line 376) | def style(self, name, value):
  class LoadMode (line 380) | class LoadMode(object):
    method __init__ (line 381) | def __init__(self, owner):
    method __call__ (line 384) | def __call__(self, value):
    method normal (line 392) | def normal(self):
    method eager (line 395) | def eager(self):
    method none (line 398) | def none(self):
  class PageScrollSetter (line 402) | class PageScrollSetter(object):
    method __init__ (line 403) | def __init__(self, scroll):
    method wait_complete (line 406) | def wait_complete(self, on_off=True):
    method smooth (line 412) | def smooth(self, on_off=True):
  class WindowSetter (line 421) | class WindowSetter(object):
    method __init__ (line 422) | def __init__(self, owner):
    method max (line 426) | def max(self):
    method mini (line 432) | def mini(self):
    method full (line 438) | def full(self):
    method normal (line 444) | def normal(self):
    method size (line 450) | def size(self, width=None, height=None):
    method location (line 460) | def location(self, x=None, y=None):
    method hide (line 468) | def hide(self):
    method show (line 471) | def show(self):
    method _get_info (line 474) | def _get_info(self):
    method _perform (line 482) | def _perform(self, bounds):

FILE: DrissionPage/_units/setter.pyi
  class BaseSetter (line 30) | class BaseSetter(object):
    method __init__ (line 33) | def __init__(self, owner: Union[Chromium, BasePage]):
    method NoneElement_value (line 39) | def NoneElement_value(self,
    method retry_times (line 49) | def retry_times(self, times: int) -> None:
    method retry_interval (line 56) | def retry_interval(self, interval: float) -> None:
    method download_path (line 63) | def download_path(self, path: Union[str, Path, None]) -> None:
  class SessionPageSetter (line 71) | class SessionPageSetter(BaseSetter):
    method __init__ (line 75) | def __init__(self, owner: SessionPage):
    method cookies (line 82) | def cookies(self) -> SessionCookiesSetter:
    method download_path (line 86) | def download_path(self, path: Union[str, Path, None]) -> None:
    method timeout (line 93) | def timeout(self, second: float) -> None:
    method encoding (line 100) | def encoding(self, encoding: Union[str, None], set_all: bool = True) -...
    method headers (line 108) | def headers(self, headers: Union[str, dict]) -> None:
    method header (line 115) | def header(self, name: str, value: str) -> None:
    method user_agent (line 123) | def user_agent(self, ua: str) -> None:
    method proxies (line 130) | def proxies(self, http: str = None, https: str = None) -> None:
    method auth (line 138) | def auth(self, auth: Union[Tuple[str, str], HTTPBasicAuth, None]) -> N...
    method hooks (line 145) | def hooks(self, hooks: Union[dict, None]) -> None:
    method params (line 152) | def params(self, params: Union[dict, None]) -> None:
    method verify (line 159) | def verify(self, on_off: Union[bool, None]) -> None:
    method cert (line 166) | def cert(self, cert: Union[str, Tuple[str, str], None]) -> None:
    method stream (line 173) | def stream(self, on_off: Union[bool, None]) -> None:
    method trust_env (line 180) | def trust_env(self, on_off: Union[bool, None]) -> None:
    method max_redirects (line 187) | def max_redirects(self, times: Union[int, None]) -> None:
    method add_adapter (line 194) | def add_adapter(self, url: str, adapter: HTTPAdapter) -> None:
  class BrowserBaseSetter (line 203) | class BrowserBaseSetter(BaseSetter):
    method __init__ (line 207) | def __init__(self, owner: ChromiumBase):
    method load_mode (line 214) | def load_mode(self) -> LoadMode:
    method timeouts (line 218) | def timeouts(self,
  class BrowserSetter (line 231) | class BrowserSetter(BrowserBaseSetter):
    method __init__ (line 235) | def __init__(self, owner: Chromium):
    method cookies (line 242) | def cookies(self) -> BrowserCookiesSetter:
    method window (line 247) | def window(self)->WindowSetter:...
    method auto_handle_alert (line 249) | def auto_handle_alert(self,
    method download_path (line 259) | def download_path(self, path: Union[Path, str, None]) -> None:
    method download_file_name (line 266) | def download_file_name(self,
    method when_download_file_exists (line 276) | def when_download_file_exists(self, mode: FILE_EXISTS) -> None:
  class ChromiumBaseSetter (line 284) | class ChromiumBaseSetter(BrowserBaseSetter):
    method __init__ (line 288) | def __init__(self, owner): ...
    method scroll (line 291) | def scroll(self) -> PageScrollSetter:
    method cookies (line 296) | def cookies(self) -> CookiesSetter:
    method headers (line 300) | def headers(self, headers: Union[dict, str]) -> None:
    method user_agent (line 307) | def user_agent(self, ua: str, platform: str = None) -> None:
    method session_storage (line 315) | def session_storage(self, item: str, value: Union[str, bool]) -> None:
    method local_storage (line 323) | def local_storage(self, item: str, value: Union[str, bool]) -> None:
    method upload_files (line 331) | def upload_files(self, files: Union[str, Path, list, tuple]) -> None:
    method auto_handle_alert (line 338) | def auto_handle_alert(self,
    method blocked_urls (line 348) | def blocked_urls(self, urls: Union[list, tuple, str, None]) -> None:
  class TabSetter (line 356) | class TabSetter(ChromiumBaseSetter):
    method __init__ (line 359) | def __init__(self, owner: ChromiumTab):
    method window (line 366) | def window(self) -> WindowSetter:
    method download_path (line 370) | def download_path(self, path: Union[str, Path, None]) -> None:
    method download_file_name (line 377) | def download_file_name(self,
    method when_download_file_exists (line 387) | def when_download_file_exists(self, mode: FILE_EXISTS) -> None:
    method activate (line 394) | def activate(self) -> None:
  class ChromiumPageSetter (line 399) | class ChromiumPageSetter(TabSetter):
    method __init__ (line 402) | def __init__(self, owner: ChromiumPage):
  class WebPageSetter (line 409) | class WebPageSetter(ChromiumPageSetter):
    method __init__ (line 414) | def __init__(self, owner: WebPage):
    method cookies (line 421) | def cookies(self) -> WebPageCookiesSetter:
  class MixTabSetter (line 426) | class MixTabSetter(TabSetter):
    method __init__ (line 431) | def __init__(self, owner: MixTab):
    method cookies (line 438) | def cookies(self) -> WebPageCookiesSetter:
    method timeouts (line 442) | def timeouts(self,
  class ChromiumElementSetter (line 455) | class ChromiumElementSetter(object):
    method __init__ (line 458) | def __init__(self, ele: ChromiumElement):
    method attr (line 464) | def attr(self, name: str, value: str = '') -> None:
    method property (line 472) | def property(self, name: str, value: str) -> None:
    method style (line 480) | def style(self, name: str, value: str) -> None:
    method innerHTML (line 488) | def innerHTML(self, html: str) -> None:
    method value (line 495) | def value(self, value: str) -> None:
  class ChromiumFrameSetter (line 503) | class ChromiumFrameSetter(ChromiumBaseSetter):
    method attr (line 506) | def attr(self, name: str, value: str) -> None:
    method property (line 514) | def property(self, name, value) -> None:
    method style (line 522) | def style(self, name, value) -> None:
  class LoadMode (line 531) | class LoadMode(object):
    method __init__ (line 535) | def __init__(self, owner: Union[Chromium, ChromiumBase]):
    method __call__ (line 541) | def __call__(self, value: Literal['normal', 'eager', 'none']) -> None:
    method normal (line 548) | def normal(self) -> None:
    method eager (line 552) | def eager(self) -> None:
    method none (line 556) | def none(self) -> None:
  class PageScrollSetter (line 561) | class PageScrollSetter(object):
    method __init__ (line 564) | def __init__(self, scroll: PageScroller):
    method wait_complete (line 570) | def wait_complete(self, on_off: bool = True):
    method smooth (line 577) | def smooth(self, on_off: bool = True):
  class WindowSetter (line 585) | class WindowSetter(object):
    method __init__ (line 590) | def __init__(self, owner: Union[ChromiumTab, ChromiumPage]):
    method max (line 596) | def max(self) -> None:
    method mini (line 600) | def mini(self) -> None:
    method full (line 604) | def full(self) -> None:
    method normal (line 608) | def normal(self) -> None:
    method size (line 612) | def size(self, width: int = None, height: int = None) -> None:
    method location (line 620) | def location(self, x: int = None, y: int = None) -> None:
    method hide (line 628) | def hide(self) -> None:
    method show (line 632) | def show(self) -> None:
    method _get_info (line 636) | def _get_info(self) -> dict:
    method _perform (line 640) | def _perform(self, bounds: dict) -> None:

FILE: DrissionPage/_units/states.py
  class ElementStates (line 12) | class ElementStates(object):
    method __init__ (line 13) | def __init__(self, ele):
    method is_selected (line 17) | def is_selected(self):
    method is_checked (line 21) | def is_checked(self):
    method is_displayed (line 25) | def is_displayed(self):
    method is_enabled (line 31) | def is_enabled(self):
    method is_alive (line 35) | def is_alive(self):
    method is_in_viewport (line 43) | def is_in_viewport(self):
    method is_whole_in_viewport (line 48) | def is_whole_in_viewport(self):
    method is_covered (line 55) | def is_covered(self):
    method is_clickable (line 64) | def is_clickable(self):
    method has_rect (line 68) | def has_rect(self):
  class ShadowRootStates (line 75) | class ShadowRootStates(object):
    method __init__ (line 76) | def __init__(self, ele):
    method is_enabled (line 80) | def is_enabled(self):
    method is_alive (line 84) | def is_alive(self):
  class BrowserStates (line 92) | class BrowserStates(object):
    method __init__ (line 93) | def __init__(self, browser):
    method is_alive (line 98) | def is_alive(self):
    method is_headless (line 102) | def is_headless(self):
    method is_existed (line 106) | def is_existed(self):
    method is_incognito (line 110) | def is_incognito(self):
  class PageStates (line 116) | class PageStates(object):
    method __init__ (line 119) | def __init__(self, owner):
    method is_loading (line 123) | def is_loading(self):
    method is_alive (line 127) | def is_alive(self):
    method ready_state (line 135) | def ready_state(self):
    method has_alert (line 139) | def has_alert(self):
    method is_headless (line 143) | def is_headless(self):
    method is_existed (line 147) | def is_existed(self):
    method is_incognito (line 151) | def is_incognito(self):
  class FrameStates (line 155) | class FrameStates(object):
    method __init__ (line 156) | def __init__(self, frame):
    method is_loading (line 160) | def is_loading(self):
    method is_alive (line 164) | def is_alive(self):
    method ready_state (line 173) | def ready_state(self):
    method is_displayed (line 177) | def is_displayed(self):
    method has_alert (line 183) | def has_alert(self):

FILE: DrissionPage/_units/states.pyi
  class ElementStates (line 16) | class ElementStates(object):
    method __init__ (line 19) | def __init__(self, ele: ChromiumElement):
    method is_selected (line 26) | def is_selected(self) -> bool:
    method is_checked (line 31) | def is_checked(self) -> bool:
    method is_displayed (line 36) | def is_displayed(self) -> bool:
    method is_enabled (line 41) | def is_enabled(self) -> bool:
    method is_alive (line 46) | def is_alive(self) -> bool:
    method is_in_viewport (line 51) | def is_in_viewport(self) -> bool:
    method is_whole_in_viewport (line 56) | def is_whole_in_viewport(self) -> bool:
    method is_covered (line 61) | def is_covered(self) -> Union[Literal[False], int]:
    method is_clickable (line 66) | def is_clickable(self) -> bool:
    method has_rect (line 71) | def has_rect(self) -> Union[Literal[False], List[Tuple[float, float]]]:
  class ShadowRootStates (line 76) | class ShadowRootStates(object):
    method __init__ (line 79) | def __init__(self, ele: ShadowRoot):
    method is_enabled (line 86) | def is_enabled(self) -> bool:
    method is_alive (line 91) | def is_alive(self) -> bool:
  class BrowserStates (line 96) | class BrowserStates(object):
    method __init__ (line 100) | def __init__(self, browser: Chromium):
    method is_alive (line 107) | def is_alive(self) -> bool:
    method is_headless (line 112) | def is_headless(self) -> bool:
    method is_existed (line 117) | def is_existed(self) -> bool:
    method is_incognito (line 122) | def is_incognito(self) -> bool:
  class PageStates (line 127) | class PageStates(object):
    method __init__ (line 130) | def __init__(self, owner: ChromiumBase):
    method is_loading (line 137) | def is_loading(self) -> bool:
    method is_alive (line 142) | def is_alive(self) -> bool:
    method ready_state (line 147) | def ready_state(self) -> Optional[str]:
    method has_alert (line 152) | def has_alert(self) -> bool:
    method is_headless (line 157) | def is_headless(self) -> bool:
    method is_existed (line 162) | def is_existed(self) -> bool:
    method is_incognito (line 167) | def is_incognito(self) -> bool:
  class FrameStates (line 172) | class FrameStates(object):
    method __init__ (line 175) | def __init__(self, frame: ChromiumFrame):
    method is_loading (line 182) | def is_loading(self) -> bool:
    method is_alive (line 187) | def is_alive(self) -> bool:
    method ready_state (line 192) | def ready_state(self) -> str:
    method is_displayed (line 197) | def is_displayed(self) -> bool:
    method has_alert (line 202) | def has_alert(self) -> bool:

FILE: DrissionPage/_units/waiter.py
  class OriginWaiter (line 15) | class OriginWaiter(object):
    method __init__ (line 16) | def __init__(self, owner):
    method __call__ (line 19) | def __call__(self, second, scope=None):
  class BrowserWaiter (line 28) | class BrowserWaiter(OriginWaiter):
    method new_tab (line 29) | def new_tab(self, timeout=None, curr_tab=None, raise_err=None):
    method download_begin (line 47) | def download_begin(self, timeout=None, cancel_it=False):
    method downloads_done (line 55) | def downloads_done(self, timeout=None, cancel_if_timeout=True):
  class BaseWaiter (line 79) | class BaseWaiter(OriginWaiter):
    method ele_deleted (line 80) | def ele_deleted(self, loc_or_ele, timeout=None, raise_err=None):
    method ele_displayed (line 84) | def ele_displayed(self, loc_or_ele, timeout=None, raise_err=None):
    method ele_hidden (line 96) | def ele_hidden(self, loc_or_ele, timeout=None, raise_err=None):
    method eles_loaded (line 109) | def eles_loaded(self, locators, timeout=None, any_one=False, raise_err...
    method load_start (line 154) | def load_start(self, timeout=None, raise_err=None):
    method doc_loaded (line 157) | def doc_loaded(self, timeout=None, raise_err=None):
    method upload_paths_inputted (line 160) | def upload_paths_inputted(self):
    method download_begin (line 168) | def download_begin(self, timeout=None, cancel_it=False):
    method url_change (line 176) | def url_change(self, text, exclude=False, timeout=None, raise_err=None):
    method title_change (line 179) | def title_change(self, text, exclude=False, timeout=None, raise_err=No...
    method _change (line 182) | def _change(self, arg, text, exclude=False, timeout=None, raise_err=No...
    method _loading (line 211) | def _loading(self, timeout=None, start=True, gap=.01, raise_err=None):
  class TabWaiter (line 227) | class TabWaiter(BaseWaiter):
    method downloads_done (line 228) | def downloads_done(self, timeout=None, cancel_if_timeout=True):
    method alert_closed (line 251) | def alert_closed(self, timeout=None):
  class ChromiumPageWaiter (line 268) | class ChromiumPageWaiter(TabWaiter):
    method new_tab (line 269) | def new_tab(self, timeout=None, raise_err=None):
    method download_begin (line 272) | def download_begin(self, timeout=None, cancel_it=False):
    method all_downloads_done (line 275) | def all_downloads_done(self, timeout=None, cancel_if_timeout=True):
  class ElementWaiter (line 279) | class ElementWaiter(OriginWaiter):
    method __init__ (line 280) | def __init__(self, owner):
    method _timeout (line 285) | def _timeout(self):
    method deleted (line 288) | def deleted(self, timeout=None, raise_err=None):
    method displayed (line 292) | def displayed(self, timeout=None, raise_err=None):
    method hidden (line 296) | def hidden(self, timeout=None, raise_err=None):
    method covered (line 300) | def covered(self, timeout=None, raise_err=None):
    method not_covered (line 305) | def not_covered(self, timeout=None, raise_err=None):
    method enabled (line 309) | def enabled(self, timeout=None, raise_err=None):
    method disabled (line 313) | def disabled(self, timeout=None, raise_err=None):
    method disabled_or_deleted (line 317) | def disabled_or_deleted(self, timeout=None, raise_err=None):
    method clickable (line 334) | def clickable(self, wait_moved=True, timeout=None, raise_err=None):
    method has_rect (line 345) | def has_rect(self, timeout=None, raise_err=None):
    method stop_moving (line 350) | def stop_moving(self, timeout=None, gap=.1, raise_err=None):
    method _wait_state (line 380) | def _wait_state(self, attr, mode=False, timeout=None, raise_err=None, ...
  class FrameWaiter (line 401) | class FrameWaiter(BaseWaiter, ElementWaiter):
    method __init__ (line 402) | def __init__(self, owner):
    method _timeout (line 407) | def _timeout(self):
  function wait_mission (line 411) | def wait_mission(browser, tid, timeout=None):

FILE: DrissionPage/_units/waiter.pyi
  class OriginWaiter (line 21) | class OriginWaiter(object):
    method __init__ (line 24) | def __init__(self, owner: Any): ...
    method __call__ (line 26) | def __call__(self, second: float, scope: float = None):
  class BrowserWaiter (line 35) | class BrowserWaiter(OriginWaiter):
    method __init__ (line 38) | def __init__(self, owner: Chromium):
    method __call__ (line 44) | def __call__(self, second: float, scope: float = None) -> Chromium:
    method new_tab (line 52) | def new_tab(self,
    method download_begin (line 64) | def download_begin(self, timeout: float = None, cancel_it: bool = Fals...
    method downloads_done (line 72) | def downloads_done(self, timeout: float = None, cancel_if_timeout: boo...
  class BaseWaiter (line 81) | class BaseWaiter(OriginWaiter):
    method ele_deleted (line 84) | def ele_deleted(self,
    method ele_displayed (line 96) | def ele_displayed(self,
    method ele_hidden (line 108) | def ele_hidden(self,
    method eles_loaded (line 120) | def eles_loaded(self,
    method load_start (line 134) | def load_start(self, timeout: float = None, raise_err: bool = None) ->...
    method doc_loaded (line 142) | def doc_loaded(self, timeout: float = None, raise_err: bool = None) ->...
    method upload_paths_inputted (line 150) | def upload_paths_inputted(self) -> bool:
    method download_begin (line 154) | def download_begin(self, timeout: float = None, cancel_it: bool = Fals...
    method url_change (line 162) | def url_change(self,
    method title_change (line 176) | def title_change(self,
    method _change (line 190) | def _change(self,
    method _loading (line 206) | def _loading(self,
  class TabWaiter (line 221) | class TabWaiter(BaseWaiter):
    method __init__ (line 224) | def __init__(self, owner: ChromiumTab):
    method __call__ (line 230) | def __call__(self,
    method downloads_done (line 240) | def downloads_done(self,
    method alert_closed (line 250) | def alert_closed(self, timeout: float = None) -> ChromiumTab:
    method url_change (line 257) | def url_change(self,
    method title_change (line 271) | def title_change(self,
  class MixTabWaiter (line 286) | class MixTabWaiter(BaseWaiter):
    method __init__ (line 289) | def __init__(self, owner: MixTab):
    method __call__ (line 295) | def __call__(self,
    method downloads_done (line 305) | def downloads_done(self,
    method alert_closed (line 315) | def alert_closed(self, timeout: float = None) -> MixTab:
    method url_change (line 322) | def url_change(self,
    method title_change (line 336) | def title_change(self,
  class ChromiumPageWaiter (line 351) | class ChromiumPageWaiter(TabWaiter):
    method __init__ (line 354) | def __init__(self, owner: ChromiumPage):
    method __call__ (line 360) | def __call__(self,
    method new_tab (line 370) | def new_tab(self,
    method all_downloads_done (line 380) | def all_downloads_done(self,
    method url_change (line 390) | def url_change(self,
    method title_change (line 404) | def title_change(self,
  class WebPageWaiter (line 419) | class WebPageWaiter(TabWaiter):
    method __init__ (line 422) | def __init__(self, owner: WebPage):
    method __call__ (line 428) | def __call__(self,
    method new_tab (line 438) | def new_tab(self,
    method all_downloads_done (line 448) | def all_downloads_done(self,
    method url_change (line 458) | def url_change(self,
    method title_change (line 472) | def title_change(self,
  class ElementWaiter (line 487) | class ElementWaiter(OriginWaiter):
    method __init__ (line 491) | def __init__(self, owner: ChromiumElement):
    method __call__ (line 497) | def __call__(self,
    method _timeout (line 508) | def _timeout(self) -> float:
    method deleted (line 512) | def deleted(self, timeout: float = None, raise_err: bool = None) -> Un...
    method displayed (line 520) | def displayed(self, timeout: float = None, raise_err: bool = None) -> ...
    method hidden (line 528) | def hidden(self, timeout: float = None, raise_err: bool = None) -> Uni...
    method covered (line 536) | def covered(self, timeout: float = None, raise_err: bool = None) -> Un...
    method not_covered (line 544) | def not_covered(self, timeout: float = None, raise_err: bool = None) -...
    method enabled (line 552) | def enabled(self, timeout: float = None, raise_err: bool = None) -> Un...
    method disabled (line 560) | def disabled(self, timeout: float = None, raise_err: bool = None) -> U...
    method disabled_or_deleted (line 568) | def disabled_or_deleted(self, timeout: float = None, raise_err: bool =...
    method clickable (line 576) | def clickable(self,
    method has_rect (line 588) | def has_rect(self,
    method stop_moving (line 598) | def stop_moving(self,
    method _wait_state (line 610) | def _wait_state(self,
  class FrameWaiter (line 627) | class FrameWaiter(BaseWaiter, ElementWaiter):
    method __init__ (line 630) | def __init__(self, owner: ChromiumFrame):
    method __call__ (line 636) | def __call__(self,
    method url_change (line 646) | def url_change(self,
    method title_change (line 660) | def title_change(self,
    method deleted (line 674) | def deleted(self, timeout: float = None, raise_err: bool = None) -> Un...
    method displayed (line 682) | def displayed(self, timeout: float = None, raise_err: bool = None) -> ...
    method hidden (line 690) | def hidden(self, timeout: float = None, raise_err: bool = None) -> Uni...
    method has_rect (line 698) | def has_rect(self,
    method covered (line 708) | def covered(self, timeout: float = None, raise_err: bool = None) -> Un...
    method not_covered (line 716) | def not_covered(self, timeout: float = None, raise_err: bool = None) -...
    method enabled (line 724) | def enabled(self, timeout: float = None, raise_err: bool = None) -> Un...
    method disabled (line 732) | def disabled(self, timeout: float = None, raise_err: bool = None) -> U...
    method disabled_or_deleted (line 740) | def disabled_or_deleted(self, timeout: float = None, raise_err: bool =...
    method clickable (line 748) | def clickable(self,
    method stop_moving (line 760) | def stop_moving(self,
  function wait_mission (line 773) | def wait_mission(browser: Chromium, tid: str, timeout: float = None) -> ...

FILE: DrissionPage/common.py
  function from_selenium (line 22) | def from_selenium(driver):
  function from_playwright (line 32) | def from_playwright(page_or_browser):

FILE: DrissionPage/errors.py
  class BaseError (line 11) | class BaseError(Exception):
    method __init__ (line 13) | def __init__(self, *args, **kwargs):
    method __str__ (line 17) | def __str__(self):
  class ElementNotFoundError (line 21) | class ElementNotFoundError(BaseError):
  class AlertExistsError (line 25) | class AlertExistsError(BaseError):
  class ContextLostError (line 29) | class ContextLostError(BaseError):
  class ElementLostError (line 33) | class ElementLostError(BaseError):
  class CDPError (line 37) | class CDPError(BaseError):
  class PageDisconnectedError (line 41) | class PageDisconnectedError(BaseError):
  class JavaScriptError (line 45) | class JavaScriptError(BaseError):
  class NoRectError (line 49) | class NoRectError(BaseError):
  class BrowserConnectError (line 53) | class BrowserConnectError(BaseError):
  class NoResourceError (line 57) | class NoResourceError(BaseError):
  class CanNotClickError (line 61) | class CanNotClickError(BaseError):
  class GetDocumentError (line 65) | class GetDocumentError(BaseError):
  class WaitTimeoutError (line 69) | class WaitTimeoutError(BaseError):
  class IncorrectURLError (line 73) | class IncorrectURLError(BaseError):
  class StorageError (line 77) | class StorageError(BaseError):
  class CookieFormatError (line 81) | class CookieFormatError(BaseError):
  class TargetNotFoundError (line 85) | class TargetNotFoundError(BaseError):
  class LocatorError (line 89) | class LocatorError(BaseError):
  class UnknownError (line 93) | class UnknownError(BaseError):
Condensed preview — 166 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,402K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 921,
    "preview": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [u"
  },
  {
    "path": ".gitignore",
    "chars": 1327,
    "preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
  },
  {
    "path": "DrissionPage/__init__.py",
    "chars": 929,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/__init__.pyi",
    "chars": 593,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_base/base.py",
    "chars": 13205,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_base/base.pyi",
    "chars": 14071,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_base/chromium.py",
    "chars": 21734,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_base/chromium.pyi",
    "chars": 9519,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_base/driver.py",
    "chars": 8210,
    "preview": "# -*- coding: utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrig"
  },
  {
    "path": "DrissionPage/_base/driver.pyi",
    "chars": 3028,
    "preview": "# -*- coding: utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrig"
  },
  {
    "path": "DrissionPage/_configs/chromium_options.py",
    "chars": 13775,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_configs/chromium_options.pyi",
    "chars": 9979,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_configs/configs.ini",
    "chars": 1051,
    "preview": "[paths]\r\ndownload_path =\r\ntmp_path =\r\n\r\n[chromium_options]\r\naddress = 127.0.0.1:9222\r\nbrowser_path = chrome\r\narguments ="
  },
  {
    "path": "DrissionPage/_configs/options_manage.py",
    "chars": 6140,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_configs/options_manage.pyi",
    "chars": 1835,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_configs/session_options.py",
    "chars": 10974,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_configs/session_options.pyi",
    "chars": 7552,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_elements/chromium_element.py",
    "chars": 55388,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_elements/chromium_element.pyi",
    "chars": 31512,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_elements/none_element.py",
    "chars": 2046,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_elements/none_element.pyi",
    "chars": 889,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_elements/session_element.py",
    "chars": 10630,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_elements/session_element.pyi",
    "chars": 10210,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/browser.py",
    "chars": 10565,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/browser.pyi",
    "chars": 1257,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/by.py",
    "chars": 411,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/cli.py",
    "chars": 1474,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/cookies.py",
    "chars": 8320,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_functions/cookies.pyi",
    "chars": 2145,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_functions/elements.py",
    "chars": 17349,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_functions/elements.pyi",
    "chars": 16473,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_functions/keys.py",
    "chars": 22285,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/keys.pyi",
    "chars": 2230,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/locator.py",
    "chars": 17811,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/locator.pyi",
    "chars": 1650,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/settings.py",
    "chars": 1825,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/settings.pyi",
    "chars": 2365,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_functions/texts.py",
    "chars": 17895,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_functions/tools.py",
    "chars": 7407,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_functions/tools.pyi",
    "chars": 2599,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/web.py",
    "chars": 10791,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_functions/web.pyi",
    "chars": 3715,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_pages/chromium_base.py",
    "chars": 37064,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_pages/chromium_base.pyi",
    "chars": 20157,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_pages/chromium_frame.py",
    "chars": 17068,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_pages/chromium_frame.pyi",
    "chars": 13615,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_pages/chromium_page.py",
    "chars": 4238,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_pages/chromium_page.pyi",
    "chars": 7372,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_pages/chromium_tab.py",
    "chars": 2418,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_pages/chromium_tab.pyi",
    "chars": 3627,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_pages/mix_tab.py",
    "chars": 7287,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_pages/mix_tab.pyi",
    "chars": 9364,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_pages/session_page.py",
    "chars": 10328,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_pages/session_page.pyi",
    "chars": 10034,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_pages/web_page.py",
    "chars": 9940,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_pages/web_page.pyi",
    "chars": 12687,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/actions.py",
    "chars": 9421,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/actions.pyi",
    "chars": 8724,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/clicker.py",
    "chars": 8751,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/clicker.pyi",
    "chars": 4871,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/console.py",
    "chars": 3142,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_units/console.pyi",
    "chars": 1557,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_units/cookies_setter.py",
    "chars": 3615,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/cookies_setter.pyi",
    "chars": 4195,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/downloader.py",
    "chars": 11130,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/downloader.pyi",
    "chars": 5257,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/listener.py",
    "chars": 20845,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/listener.pyi",
    "chars": 12375,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/rect.py",
    "chars": 7102,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/rect.pyi",
    "chars": 5301,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/screencast.py",
    "chars": 7129,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/screencast.pyi",
    "chars": 2168,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/scroller.py",
    "chars": 4488,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/scroller.pyi",
    "chars": 8274,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/selector.py",
    "chars": 5678,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_units/selector.pyi",
    "chars": 6757,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/setter.py",
    "chars": 17710,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/setter.pyi",
    "chars": 15736,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/states.py",
    "chars": 5309,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/states.pyi",
    "chars": 4264,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/_units/waiter.py",
    "chars": 17270,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/_units/waiter.pyi",
    "chars": 24588,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/common.py",
    "chars": 2185,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/errors.py",
    "chars": 1444,
    "preview": "# -*- coding:utf-8 -*-\r\n\"\"\"\r\n@Author   : g1879\r\n@Contact  : g1879@qq.com\r\n@Website  : https://DrissionPage.cn\r\n@Copyrigh"
  },
  {
    "path": "DrissionPage/items.py",
    "chars": 660,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "DrissionPage/version.py",
    "chars": 191,
    "preview": "# -*- coding:utf-8 -*-\n\"\"\"\n@Author   : g1879\n@Contact  : g1879@qq.com\n@Website  : https://DrissionPage.cn\n@Copyright: (c"
  },
  {
    "path": "LICENSE",
    "chars": 1937,
    "preview": "Copyright (c) 2020, g1879\r\nAll rights reserved.\r\n\r\n允许任何人以个人身份使用或分发本项目源代码,但仅限于学习和合法非盈利目的。\r\n\r\n个人或组织如未获得版权持有人授权,不得将本项目以源代码或"
  },
  {
    "path": "MANIFEST.in",
    "chars": 174,
    "preview": "include DrissionPage/_configs/configs.ini\r\ninclude DrissionPage/_functions/suffixes.dat\r\ninclude DrissionPage/*.pyi\r\ninc"
  },
  {
    "path": "README.md",
    "chars": 2149,
    "preview": "# ✨️ 概述\r\n\r\nDrissionPage 是一个基于 python 的网页自动化工具。\r\n\r\n它既能控制浏览器,也能收发数据包,还能把两者合而为一。\r\n\r\n可兼顾浏览器自动化的便利性和 requests 的高效率。\r\n\r\n它功能强大,"
  },
  {
    "path": "docs_en/.nojekyll",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs_en/ChromiumPage/actions.md",
    "chars": 19650,
    "preview": "## 🚤 Actions Chain\n\nActions Chain can perform a series of interactive actions on the browser, such as mouse movement, mo"
  },
  {
    "path": "docs_en/ChromiumPage/browser_options.md",
    "chars": 25277,
    "preview": "🚤 Browser Startup Settings\n---\n\nThe browser's startup configuration is very complicated. This library uses the `Chromium"
  },
  {
    "path": "docs_en/ChromiumPage/create_page_object.md",
    "chars": 12899,
    "preview": "🚤 Create Page Object\n---\n\nBoth `ChromiumPage` and `WebPage` objects can send and receive data packets in d-mode. This se"
  },
  {
    "path": "docs_en/ChromiumPage/element_operation.md",
    "chars": 25330,
    "preview": "🚤 Element Interaction\n---\n\nThis section introduces the interaction with browser elements. The browser element object is "
  },
  {
    "path": "docs_en/ChromiumPage/frame_operation.md",
    "chars": 15299,
    "preview": "🚤 iframe Operation\n---\n\nThe `<iframe>` element is a special element that is both an element and a page, so a separate se"
  },
  {
    "path": "docs_en/ChromiumPage/get_element_info.md",
    "chars": 12862,
    "preview": "🚤 Get Element Information\n---\n\nThe objects corresponding to browser elements are `ChromiumElement` and `ShadowRoot`. In "
  },
  {
    "path": "docs_en/ChromiumPage/get_elements.md",
    "chars": 137,
    "preview": "🚤 Find Elements\n---\n\nPlease refer to the \"[Find Elements](https://g1879.gitee.io/drissionpagedocs/get_elements/get_ele_i"
  },
  {
    "path": "docs_en/ChromiumPage/get_page_info.md",
    "chars": 10380,
    "preview": "🚤 Getting Page Information\n---\n\nAfter successfully accessing the web page, you can use the properties and methods of `Ch"
  },
  {
    "path": "docs_en/ChromiumPage/introduction.md",
    "chars": 1972,
    "preview": "🚤 Overview\n---\n\nThe `ChromiumPage` object and the `WebPage` object are d models for manipulating the browser. This chapt"
  },
  {
    "path": "docs_en/ChromiumPage/network_listener.md",
    "chars": 13665,
    "preview": "🚤 Listening to Network Data\n---\n\nMany web page data comes from interfaces, dynamically loaded during website usage, such"
  },
  {
    "path": "docs_en/ChromiumPage/page_operation.md",
    "chars": 26157,
    "preview": "🚤 Page Interaction\n---\n\nThis section introduces the browser page interaction feature, while element interaction is cover"
  },
  {
    "path": "docs_en/ChromiumPage/screen_recording.md",
    "chars": 7912,
    "preview": "🚤 Screenshots and Recordings\n---\n\n## ✅️️ Page Screenshots\n\nUse the `get_screenshot()` method of the page object to take "
  },
  {
    "path": "docs_en/ChromiumPage/tab_operation.md",
    "chars": 18687,
    "preview": "🚤 Tab Page Operations\n---\n\nThis section introduces the management and usage skills of browser tabs.\n\nA Tab object (`Chro"
  },
  {
    "path": "docs_en/ChromiumPage/upload_files.md",
    "chars": 601,
    "preview": "🚤 File Upload\n---\n\nThere are two ways to upload a file:\n\n- Find the `<input>` element and insert the file path.\n\n- Inter"
  },
  {
    "path": "docs_en/ChromiumPage/visit_web_page.md",
    "chars": 4921,
    "preview": "🚤 Visit Web Page\n---\n\nBoth `ChromiumPage` and `WebPage` objects can control browser access to web pages. Here we will on"
  },
  {
    "path": "docs_en/ChromiumPage/waiting.md",
    "chars": 23250,
    "preview": "🚤 Automatic Waiting\n---\n\nIn unstable network environments, it is difficult to determine the execution time of JavaScript"
  },
  {
    "path": "docs_en/MixPage/introduction.md",
    "chars": 1210,
    "preview": "🛠 Old Version (MixPage)\n---\n\nThe versions of this repository prior to 3.0 were implemented by re-encapsulating selenium."
  },
  {
    "path": "docs_en/Q&A.md",
    "chars": 4021,
    "preview": "# ❓ Q&A'\nhide:\n  - navigation\n---\n\nThis page collects some frequently asked questions from users during the usage proces"
  },
  {
    "path": "docs_en/README_en.md",
    "chars": 8116,
    "preview": "# ✨️ Overview\n\nDrissionPage is a web automation tool based on Python.\n\nIt can control browsers, send and receive data pa"
  },
  {
    "path": "docs_en/SessionPage/create_page_object.md",
    "chars": 4562,
    "preview": "🚄 Creating Page Objects\n---\n\nBoth the `SessionPage` and `WebPage` objects can send and receive packets. In this section,"
  },
  {
    "path": "docs_en/SessionPage/get_element_info.md",
    "chars": 5831,
    "preview": "🚄 Get Element Information\n---\n\nThe `SessionPage` object and `WebPage` object retrieve elements in `SessionElement` mode."
  },
  {
    "path": "docs_en/SessionPage/get_elements.md",
    "chars": 79,
    "preview": "🚄 Search for Elements\n---\n\nPlease refer to the \"Search for Elements\" section.\n\n"
  },
  {
    "path": "docs_en/SessionPage/get_page_info.md",
    "chars": 4846,
    "preview": "🚄 Get Page Info\n---\n\nAfter successfully accessing the webpage, you can use the attributes and methods of `SessionPage` t"
  },
  {
    "path": "docs_en/SessionPage/introduction.md",
    "chars": 1879,
    "preview": "🚄 Overview\n---\n\nThe `SessionPage` object and the `WebPage` object's s pattern allow you to access web pages in the form "
  },
  {
    "path": "docs_en/SessionPage/session_options.md",
    "chars": 13652,
    "preview": "🚄 Session Options\n---\n\nThis section introduces the startup configuration of the `SessionPage`.\n\nWe manage the initial co"
  },
  {
    "path": "docs_en/SessionPage/set_session.md",
    "chars": 7501,
    "preview": "🚄 Page Settings\n---\n\nThis section introduces the settings of `SessionPage`.\n\nThese settings are global parameters, and t"
  },
  {
    "path": "docs_en/SessionPage/visit_web_page.md",
    "chars": 5653,
    "preview": "🚄 Visit Web Page\n---\n\nThe s mode of `SessionPage` and `WebPage` is based on the requests library for network connections"
  },
  {
    "path": "docs_en/WebPage/create_page_object.md",
    "chars": 4671,
    "preview": "🛸 Create Page Object\n---\n\nThis section introduces the creation of the `WebPage` object.\n\nThe `WebPage` object has two mo"
  },
  {
    "path": "docs_en/WebPage/introduction.md",
    "chars": 837,
    "preview": "🛸 Overview\n---\n\nThe `WebPage` object integrates `SessionPage` and `ChromiumPage`, enabling communication between the two"
  },
  {
    "path": "docs_en/WebPage/mode_switch.md",
    "chars": 3326,
    "preview": "🛸 Mode Change\n---\n\nThis section introduces the mode change function of `WebPage`.\n\nThe d mode of `WebPage` behaves the s"
  },
  {
    "path": "docs_en/WebPage/webpage_function.md",
    "chars": 2739,
    "preview": "🛸 Unique Features\n---\n\nThis section introduces the unique features of `WebPage`.\n\n`WebPage` is integrated with `Chromium"
  },
  {
    "path": "docs_en/advance/accelerate_reading.md",
    "chars": 3177,
    "preview": "⚙️ Speed Up Data Retrieval\n---\n\nThis section demonstrates a black technology that can greatly accelerate data collection"
  },
  {
    "path": "docs_en/advance/commands.md",
    "chars": 2206,
    "preview": "⚙️ Using Command Line\n---\n\nDrissionPage provides some convenient command line commands for basic settings, instead of us"
  },
  {
    "path": "docs_en/advance/errors.md",
    "chars": 2008,
    "preview": "⚙️ Usage of Exceptions\n---\n\nThis section introduces custom exceptions in DrissionPage.\n\n## ✅️️ Import\n\nVarious exception"
  },
  {
    "path": "docs_en/advance/ini_file.md",
    "chars": 5099,
    "preview": "⚙️ Using Configuration Files\n---\n\nThis library uses ini files to record the startup configuration of browsers or `Sessio"
  },
  {
    "path": "docs_en/advance/packaging.md",
    "chars": 3492,
    "preview": "⚙️ Packaging Program\n---\n\nThis section describes things to consider when packaging a program.\n\n## ✅️️ Use a new virtual "
  },
  {
    "path": "docs_en/advance/settings.md",
    "chars": 1432,
    "preview": "⚙️ Global Settings\n---\n\nThere are some global settings at runtime that can control certain behaviors of the program.\n\n##"
  },
  {
    "path": "docs_en/advance/tools.md",
    "chars": 4268,
    "preview": "⚙️ Tools\n---\n\nThe `DrissionPage.common` module provides several small tools.\n\n## ✅️️ `make_session_ele()`\n\nThis method i"
  },
  {
    "path": "docs_en/cooperation.md",
    "chars": 96,
    "preview": "---\nid: cooper\ntitle: Business cooperation\n---\n\nUndertake automated orders, contact QQ:178691442"
  },
  {
    "path": "docs_en/demos/douban_book_pics.md",
    "chars": 1531,
    "preview": "🌠 Download Douban Book Covers\n---\n\nThe example from Starbucks uses the `download()` method to download images. This exam"
  },
  {
    "path": "docs_en/demos/login_gitee.md",
    "chars": 1389,
    "preview": "🌠 Gitee Auto Login\n---\n\nThis example demonstrates how to automatically login to the Gitee website by controlling the bro"
  },
  {
    "path": "docs_en/demos/maoyan_TOP100.md",
    "chars": 2316,
    "preview": "🌠 Collecting Maoyan Movie Rankings\n---\n\nThis example demonstrates data collection using a web browser.\n\n## ✅️️ Collectio"
  },
  {
    "path": "docs_en/demos/multithreading_with_tabs.md",
    "chars": 3258,
    "preview": "🌠 Multi-threaded Operation of Tabs\n---\n\nThis example demonstrates how to use multiple threads to simultaneously control "
  },
  {
    "path": "docs_en/demos/starbucks_pics.md",
    "chars": 2976,
    "preview": "🌠 Download Starbucks Product Images\n---\n\nThis example demonstrates the functionality of the `download()` method.\n\n## ✅️️"
  },
  {
    "path": "docs_en/download/DownloadKit.md",
    "chars": 6978,
    "preview": "# ⤵️ DownloadKit\n\nThe `DrissionPage` module comes with a built-in download tool called DownloadKit, which provides funct"
  },
  {
    "path": "docs_en/download/browser.md",
    "chars": 12549,
    "preview": "⤵️ Browser Download\n---\n\nThis section introduces the functionality for setting up browser download tasks.\n\n## ✅️ Overvie"
  },
  {
    "path": "docs_en/download/introduction.md",
    "chars": 1571,
    "preview": "⤵️ Overview\n---\n\nDrissionPage provides powerful file download management capabilities.\n\nIt can initiate download tasks a"
  },
  {
    "path": "docs_en/features/features_demos/compare_with_requests.md",
    "chars": 1046,
    "preview": "⭐ Comparison with requests\n---\n\nThe following code achieves the same functionality, comparing the amount of code for eac"
  },
  {
    "path": "docs_en/features/features_demos/compare_with_selenium.md",
    "chars": 2235,
    "preview": "⭐ Comparison with selenium\n---\n\nThe following code achieves the same functionality, comparing the code size of both:\n\n🔸 "
  },
  {
    "path": "docs_en/features/features_demos/download_file.md",
    "chars": 325,
    "preview": "# Download Files\n\nDrissionPage comes with a convenient downloader that allows you to easily download files with just one"
  },
  {
    "path": "docs_en/features/features_demos/get_element_attributes.md",
    "chars": 628,
    "preview": "⭐ Get Element Attribute\n---\n\n```python\n# Continuing from previous code\nfoot = page.ele('#footer-left')  # Find element b"
  },
  {
    "path": "docs_en/features/features_demos/switch_mode.md",
    "chars": 773,
    "preview": "⭐ Mode Switch\n---\n\nLog in to the website using a browser and switch to reading the webpage with requests. They will shar"
  },
  {
    "path": "docs_en/features/intimate_design.md",
    "chars": 5619,
    "preview": "💖 Intimate Design\n---\n\nHere is an introduction to some of the user-friendly designs built into this library.\n\n## ✅️️ Uni"
  },
  {
    "path": "docs_en/get_elements/cheat_sheet.md",
    "chars": 4954,
    "preview": "🔦 Syntax Cheat Sheet\n---\n\n## ✅️ Syntax for Positioning\n\n### 📌 Basic Usage\n\nThe following syntax only appears at the begi"
  },
  {
    "path": "docs_en/get_elements/introduction.md",
    "chars": 4807,
    "preview": "🔦 Overview\n---\n\nThis chapter introduces how to get element objects.\n\nPositioning elements is a critical skill in automat"
  },
  {
    "path": "docs_en/get_elements/more.md",
    "chars": 11590,
    "preview": "🔦 More Usages\n---\n\nThis section introduces the ways to access element objects in a browser page.\n\nThe methods for obtain"
  },
  {
    "path": "docs_en/get_elements/not_found.md",
    "chars": 2911,
    "preview": "# 🔦 Element Not Found\n\n## ✅️ Default Behavior\n\nBy default, when an element is not found, an `NoneElement` object is retu"
  },
  {
    "path": "docs_en/get_elements/simplify.md",
    "chars": 2761,
    "preview": "🔦 Simplified Syntax\n---\n\nTo further simplify the code, the syntax for positioning can be expressed in a simplified form,"
  },
  {
    "path": "docs_en/get_elements/usage.md",
    "chars": 31496,
    "preview": "## 🔦 Basic Usage\n\n## ✅️️ Methods for finding elements\n\n### 📌 `ele()`\n\nBoth the page object and the element object have t"
  },
  {
    "path": "docs_en/get_start/basic_concept.md",
    "chars": 13355,
    "preview": "## ☀️ Basic Concepts\n\nThis section explains some basic concepts of DrissionPage and gives an overview of its structure.\n"
  },
  {
    "path": "docs_en/get_start/before_start.md",
    "chars": 3727,
    "preview": "🌏 Preparations\n---\n\nBefore we begin, let's do some simple setup.\n\nIf you only need to send and receive data packets, no "
  },
  {
    "path": "docs_en/get_start/examples/control_browser.md",
    "chars": 3061,
    "preview": "🗺️ Controlling the Browser\n---\n\nNow, let's understand how DrissionPage works through some examples.\n\nThis example demons"
  },
  {
    "path": "docs_en/get_start/examples/data_packets.md",
    "chars": 3182,
    "preview": "🗺️ Sending and Receiving Data Packets\n---\n\nThis example demonstrates how to use the `SessionPage` to collect data from t"
  },
  {
    "path": "docs_en/get_start/examples/switch_mode.md",
    "chars": 4050,
    "preview": "🗺️ Switch Mode\n---\n\nThis example demonstrates how to switch between controlling the browser and sending/receiving packet"
  },
  {
    "path": "docs_en/get_start/import.md",
    "chars": 3308,
    "preview": "# 🌏 Import\n---\n\n## ✅️ Page Classes\n\nPage classes are the main tools used to control the browser or send/receive data pac"
  },
  {
    "path": "docs_en/get_start/installation.md",
    "chars": 508,
    "preview": "🌏 Installation\n---\n\n## ✅️️ System Requirements\n\nOperating System: Windows, Linux, or Mac.\n\nPython Version: 3.6 and above"
  },
  {
    "path": "docs_en/history/1.x.md",
    "chars": 3530,
    "preview": "# v0.x-v1.4\ndescription: DrissionPage Version History\n---\n\nVersions v0.x to v1.4 were made based on selenium and request"
  },
  {
    "path": "docs_en/history/2.x.md",
    "chars": 9066,
    "preview": "# v1.5-v2.x\ndescription: DrissionPage Version History\n---\n\nVersion 1.5 to 2.x, control the browser based on selenium and"
  },
  {
    "path": "docs_en/history/3.x.md",
    "chars": 14138,
    "preview": "description: DrissionPage Version History\n---\n\n## v3.2.35\n\n- Fixed an issue where simulated actions were not responding "
  },
  {
    "path": "docs_en/history/4.x.md",
    "chars": 14077,
    "preview": "v4.x\n---\n\n## v4.0.3.3\n\nThis version of the project has undergone a significant refactor and introduced many new features"
  },
  {
    "path": "docs_en/history/statement.md",
    "chars": 8443,
    "preview": "Self-Introduction\n---\n\n## ✅️ Introduction\n\nA few years ago, there was a very strange system.\n\nIts business logic was ext"
  },
  {
    "path": "docs_en/usage_introduction.md",
    "chars": 3555,
    "preview": "Introduction to Usage\n---\n\nThis chapter provides a detailed overview of several page objects and their usage.\n\nIn the \"G"
  },
  {
    "path": "docs_en/whatsnew/3_2.md",
    "chars": 15017,
    "preview": "💥 3.2 Function Introduction\n---\n3.2 has significant changes compared to 3.1. It has streamlined the underlying logic, fi"
  },
  {
    "path": "docs_en/whatsnew/4_0.md",
    "chars": 30960,
    "preview": "💥 4.0 Function Introduction\n---\n\n3.x was a preliminary attempt to independently develop the underlying framework. Many a"
  },
  {
    "path": "requirements.txt",
    "chars": 97,
    "preview": "requests\r\nlxml\r\ncssselect\r\nDownloadKit>=2.0.7\r\nwebsocket-client\r\nclick\r\ntldextract>=3.4.4\r\npsutil"
  },
  {
    "path": "setup.py",
    "chars": 1273,
    "preview": "# -*- coding:utf-8 -*-\r\nfrom setuptools import setup, find_packages\r\nfrom DrissionPage import __version__\r\n\r\nwith open(\""
  }
]

About this extraction

This page contains the full source code of the g1879/DrissionPage GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 166 files (1.3 MB), approximately 336.5k tokens, and a symbol index with 2576 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!