From 91479ee701c3ba822cee132b1941d3970c6cd866 Mon Sep 17 00:00:00 2001 From: g1879 Date: Wed, 11 Jan 2023 18:23:21 +0800 Subject: [PATCH] =?UTF-8?q?SessionPage=E4=B9=9F=E5=8F=AF=E4=BB=A5=E4=BB=8E?= =?UTF-8?q?ini=E8=AF=BB=E5=8F=96timeout=EF=BC=9Bini=E4=B8=ADsession?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=A2=9E=E5=8A=A0timeout=E9=A1=B9=EF=BC=9BSe?= =?UTF-8?q?ssionOptions=E5=A2=9E=E5=8A=A0timeout=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/chromium_base.py | 12 +- DrissionPage/chromium_base.pyi | 6 +- DrissionPage/chromium_page.py | 3 +- DrissionPage/config.py | 6 +- DrissionPage/config.pyi | 1 + DrissionPage/configs.ini | 2 +- DrissionPage/drission.py | 6 - DrissionPage/driver_element.py | 5 - DrissionPage/driver_page.py | 6 - DrissionPage/session_page.py | 9 +- DrissionPage/session_page.pyi | 2 +- DrissionPage/web_page.py | 64 +++++-- DrissionPage/web_page.pyi | 10 +- docs/WebPage使用方法/3.10动作链.md | 184 +++++++++---------- docs/WebPage使用方法/3.1创建页面对象.md | 232 +++++++++++++----------- docs/版本历史.md | 9 +- setup.py | 2 +- 17 files changed, 299 insertions(+), 260 deletions(-) diff --git a/DrissionPage/chromium_base.py b/DrissionPage/chromium_base.py index 88f02a5..5bb649c 100644 --- a/DrissionPage/chromium_base.py +++ b/DrissionPage/chromium_base.py @@ -25,13 +25,14 @@ class ChromiumBase(BasePage): :param tab_id: 要控制的标签页id,不指定默认为激活的 :param timeout: 超时时间 """ - super().__init__(timeout) self._is_loading = None self._root_id = None self._debug = False self._debug_recorder = None self.timeouts = Timeout(self) self._connect_browser(address, tab_id) + timeout = timeout if timeout is not None else self.timeouts.implicit + super().__init__(timeout) def _connect_browser(self, addr_driver_opts=None, tab_id=None): """连接浏览器,在第一次时运行 \n @@ -280,7 +281,7 @@ class ChromiumBase(BasePage): :return: None """ if implicit is not None: - self.timeout = implicit + self.timeouts.implicit = implicit if page_load is not None: self.timeouts.page_load = page_load @@ -661,14 +662,11 @@ class Timeout(object): """用于保存d模式timeout信息的类""" def __init__(self, page): - self.page = page + self._page = page + self.implicit = 10 self.page_load = 30 self.script = 30 - @property - def implicit(self): - return self.page.timeout - class PageLoadStrategy(object): """用于设置页面加载策略的类""" diff --git a/DrissionPage/chromium_base.pyi b/DrissionPage/chromium_base.pyi index ec2caa7..16512d9 100644 --- a/DrissionPage/chromium_base.pyi +++ b/DrissionPage/chromium_base.pyi @@ -193,13 +193,11 @@ class ChromiumBase(BasePage): class Timeout(object): def __init__(self, page: ChromiumBase): - self.page: ChromiumBase = ... + self._page: ChromiumBase = ... + self.implicit: float = ... self.page_load: float = ... self.script: float = ... - @property - def implicit(self) -> float: ... - class PageLoadStrategy(object): def __init__(self, page: ChromiumBase): diff --git a/DrissionPage/chromium_page.py b/DrissionPage/chromium_page.py index bd22cfd..052989d 100644 --- a/DrissionPage/chromium_page.py +++ b/DrissionPage/chromium_page.py @@ -88,9 +88,10 @@ class ChromiumPage(ChromiumBase): self._tab_obj.Page.javascriptDialogClosed = self._on_alert_close def _set_options(self): + """从配置中读取设置""" self.set_timeouts(page_load=self.options.timeouts['pageLoad'] / 1000, script=self.options.timeouts['script'] / 1000, - implicit=self.options.timeouts['implicit'] / 1000 if self.timeout is None else self.timeout) + implicit=self.options.timeouts['implicit'] / 1000) self._page_load_strategy = self.options.page_load_strategy @property diff --git a/DrissionPage/config.py b/DrissionPage/config.py index 2dd9128..c09af09 100644 --- a/DrissionPage/config.py +++ b/DrissionPage/config.py @@ -42,7 +42,6 @@ class OptionsManager(object): """返回paths设置""" if self._paths is None: self._paths = self.get_option('paths') - return self._paths @property @@ -50,7 +49,6 @@ class OptionsManager(object): """返回chrome设置""" if self._chrome_options is None: self._chrome_options = self.get_option('chrome_options') - return self._chrome_options @property @@ -58,7 +56,6 @@ class OptionsManager(object): """返回session设置""" if self._session_options is None: self._session_options = self.get_option('session_options') - return self._session_options def get_value(self, section, item): @@ -151,6 +148,7 @@ class SessionOptions(object): self._stream = None self._trust_env = None self._max_redirects = None + self.timeout = 10 if read_file: self.ini_path = ini_path or str(Path(__file__).parent / 'configs.ini') @@ -193,6 +191,8 @@ class SessionOptions(object): if options_dict.get('max_redirects', None) is not None: self._max_redirects = options_dict['max_redirects'] + self.timeout = options_dict.get('timeout', 10) + @property def headers(self): """返回headers设置信息""" diff --git a/DrissionPage/config.pyi b/DrissionPage/config.pyi index 871da6b..ffe58c9 100644 --- a/DrissionPage/config.pyi +++ b/DrissionPage/config.pyi @@ -58,6 +58,7 @@ class SessionOptions(object): self._stream: bool = ... self._trust_env: bool = ... self._max_redirects: int = ... + self.timeout: float = ... @property def headers(self) -> dict: ... diff --git a/DrissionPage/configs.ini b/DrissionPage/configs.ini index 763cf8b..3ea4625 100644 --- a/DrissionPage/configs.ini +++ b/DrissionPage/configs.ini @@ -18,4 +18,4 @@ headers = { "Connection": "keep-alive", "Accept-Charset": "GB2312,utf-8;q=0.7,*;q=0.7" } - +timeout = 10 \ No newline at end of file diff --git a/DrissionPage/drission.py b/DrissionPage/drission.py index b2cbccb..a306171 100644 --- a/DrissionPage/drission.py +++ b/DrissionPage/drission.py @@ -113,12 +113,6 @@ class Drission(object): if active_tab != self._driver.current_window_handle: self._driver.switch_to.window(active_tab) - # 反反爬设置 - try: - self._driver.execute_script('Object.defineProperty(navigator,"webdriver",{get:() => undefined,});') - except Exception: - pass - return self._driver @property diff --git a/DrissionPage/driver_element.py b/DrissionPage/driver_element.py index 57a8fdb..0c5c8ec 100644 --- a/DrissionPage/driver_element.py +++ b/DrissionPage/driver_element.py @@ -329,7 +329,6 @@ class DriverElement(DrissionElement): :param filter_loc: 筛选条件,可用selenium的(By, str),也可用本库定位语法 :return: DriverElement对象 """ - index, filter_loc = _exchange_arguments(index, filter_loc) eles = self._get_relative_eles('left', filter_loc) return eles[index - 1] if index <= len(eles) else None @@ -339,7 +338,6 @@ class DriverElement(DrissionElement): :param filter_loc: 筛选条件,可用selenium的(By, str),也可用本库定位语法 :return: DriverElement对象 """ - index, filter_loc = _exchange_arguments(index, filter_loc) eles = self._get_relative_eles('right', filter_loc) return eles[index - 1] if index <= len(eles) else None @@ -349,7 +347,6 @@ class DriverElement(DrissionElement): :param filter_loc: 筛选条件,可用selenium的(By, str),也可用本库定位语法 :return: DriverElement对象 """ - index, filter_loc = _exchange_arguments(index, filter_loc) eles = self._get_relative_eles('left', filter_loc) return eles[index - 1] if index <= len(eles) else None @@ -359,7 +356,6 @@ class DriverElement(DrissionElement): :param filter_loc: 筛选条件,可用selenium的(By, str),也可用本库定位语法 :return: DriverElement对象 """ - index, filter_loc = _exchange_arguments(index, filter_loc) eles = self._get_relative_eles('left', filter_loc) return eles[index - 1] if index <= len(eles) else None @@ -369,7 +365,6 @@ class DriverElement(DrissionElement): :param filter_loc: 筛选条件,可用selenium的(By, str),也可用本库定位语法 :return: DriverElement对象 """ - index, filter_loc = _exchange_arguments(index, filter_loc) eles = self._get_relative_eles('near', filter_loc) return eles[index - 1] if index <= len(eles) else None diff --git a/DrissionPage/driver_page.py b/DrissionPage/driver_page.py index 3610993..68d6b26 100644 --- a/DrissionPage/driver_page.py +++ b/DrissionPage/driver_page.py @@ -67,12 +67,6 @@ class DriverPage(BasePage): """ retry, interval = self._before_connect(url, retry, interval) self._url_available = self._d_connect(self._url, times=retry, interval=interval, show_errmsg=show_errmsg) - - try: - self._driver.execute_script('Object.defineProperty(navigator,"webdriver",{get:() => undefined,});') - except Exception: - pass - return self._url_available def ele(self, loc_or_ele, timeout=None): diff --git a/DrissionPage/session_page.py b/DrissionPage/session_page.py index 87a516a..f3a6a9b 100644 --- a/DrissionPage/session_page.py +++ b/DrissionPage/session_page.py @@ -20,14 +20,16 @@ from .session_element import SessionElement, make_session_ele class SessionPage(BasePage): """SessionPage封装了页面操作的常用功能,使用requests来获取、解析网页""" - def __init__(self, session_or_options=None, timeout=10): + def __init__(self, session_or_options=None, timeout=None): """初始化 \n :param session_or_options: Session对象或SessionOptions对象 - :param timeout: 连接超时时间 + :param timeout: 连接超时时间,为None时从ini文件读取 """ - super().__init__(timeout) self._response = None + self.timeout = 10 self._create_session(session_or_options) + timeout = timeout if timeout is not None else self.timeout + super().__init__(timeout) def _create_session(self, Session_or_Options): """创建内建Session对象 @@ -37,6 +39,7 @@ class SessionPage(BasePage): if Session_or_Options is None or isinstance(Session_or_Options, SessionOptions): options = Session_or_Options or SessionOptions() self._set_session(options.as_dict()) + self.timeout = options.timeout elif isinstance(Session_or_Options, Session): self._session = Session_or_Options diff --git a/DrissionPage/session_page.pyi b/DrissionPage/session_page.pyi index fcb3382..2c8a31c 100644 --- a/DrissionPage/session_page.pyi +++ b/DrissionPage/session_page.pyi @@ -18,7 +18,7 @@ from .config import SessionOptions class SessionPage(BasePage): def __init__(self, session_or_options: Union[Session, SessionOptions] = None, - timeout: float = 10): + timeout: float = None): self._session: Session = ... self._url: str = ... self._response: Response = ... diff --git a/DrissionPage/web_page.py b/DrissionPage/web_page.py index 600dfb9..c95fdfc 100644 --- a/DrissionPage/web_page.py +++ b/DrissionPage/web_page.py @@ -19,9 +19,10 @@ from .chromium_driver import ChromiumDriver class WebPage(SessionPage, ChromiumPage, BasePage): """整合浏览器和request的页面类""" - def __init__(self, mode='d', timeout=10, tab_id=None, driver_or_options=None, session_or_options=None): + def __init__(self, mode='d', timeout=None, tab_id=None, driver_or_options=None, session_or_options=None): """初始化函数 \n :param mode: 'd' 或 's',即driver模式和session模式 + :param tab_id: 要控制的标签页id,不指定默认为激活的 :param timeout: 超时时间,d模式时为寻找元素时间,s模式时为连接时间,默认10秒 :param driver_or_options: ChromiumDriver对象或DriverOptions对象,只使用s模式时应传入False :param session_or_options: Session对象或SessionOptions对象,只使用d模式时应传入False @@ -32,7 +33,6 @@ class WebPage(SessionPage, ChromiumPage, BasePage): self._debug = False self._debug_recorder = None - super(ChromiumBase, self).__init__(timeout) # 调用Base的__init__() self._session = None self._tab_obj = None self._is_loading = False @@ -46,6 +46,9 @@ class WebPage(SessionPage, ChromiumPage, BasePage): if self._mode == 'd': self._to_d_mode() + t = timeout if timeout is not None else self.timeouts.implicit + super(ChromiumBase, self).__init__(t) # 调用Base的__init__() + def __call__(self, loc_or_str, timeout=None): """在内部查找元素 \n 例:ele = page('@id=ele_id') \n @@ -138,6 +141,19 @@ class WebPage(SessionPage, ChromiumPage, BasePage): """返回 session 保存的url""" return self._response.url if self._response else None + @property + def timeout(self): + """返回通用timeout设置""" + return self.timeouts.implicit + + @timeout.setter + def timeout(self, second): + """设置通用超时时间 \n + :param second: 秒数 + :return: None + """ + self.set_timeouts(implicit=second) + def get(self, url, show_errmsg=False, retry=None, interval=None, timeout=None, **kwargs): """跳转到一个url \n :param url: 目标url @@ -368,44 +384,58 @@ class WebPage(SessionPage, ChromiumPage, BasePage): return super(SessionPage, self)._ele(loc_or_ele, timeout=timeout, single=single, relative=relative) def _set_driver_options(self, driver_or_Options): - """处理driver设置""" + """处理driver设置 + :param driver_or_Options: ChromiumDriver对象或DriverOptions对象 + :return: None + """ + if isinstance(driver_or_Options, ChromiumDriver): + self._connect_browser(driver_or_Options) + self._has_driver = True + return + if driver_or_Options is None: self._driver_options = DriverOptions() elif driver_or_Options is False: self._driver_options = DriverOptions(read_file=False) - elif isinstance(driver_or_Options, ChromiumDriver): - self._connect_browser(driver_or_Options) - self._has_driver = True - elif isinstance(driver_or_Options, DriverOptions): self._driver_options = driver_or_Options else: raise TypeError('driver_or_options参数只能接收WebDriver, Options, DriverOptions或False。') + timeouts = self._driver_options.timeouts + self.set_timeouts(timeouts['implicit'], timeouts['pageLoad'], timeouts['script']) + def _set_session_options(self, Session_or_Options): - """处理session设置""" - if Session_or_Options is None: - self._session_options = SessionOptions().as_dict() - - elif Session_or_Options is False: - self._session_options = SessionOptions(read_file=False).as_dict() - - elif isinstance(Session_or_Options, Session): + """处理session设置 + :param Session_or_Options: Session对象或SessionOptions对象 + :return: None + """ + if isinstance(Session_or_Options, Session): self._session = Session_or_Options self._has_session = True + return + + if Session_or_Options is None: + so = SessionOptions() + + elif Session_or_Options is False: + so = SessionOptions(read_file=False) elif isinstance(Session_or_Options, SessionOptions): - self._session_options = Session_or_Options.as_dict() + so = Session_or_Options elif isinstance(Session_or_Options, dict): - self._session_options = Session_or_Options + so = Session_or_Options else: raise TypeError('session_or_options参数只能接收Session, dict, SessionOptions或False。') + self._session_options = so.as_dict() + self.set_timeouts(implicit=so.timeout) + def quit(self): """关闭浏览器,关闭session""" if self._has_session: diff --git a/DrissionPage/web_page.pyi b/DrissionPage/web_page.pyi index c7a7edd..b068044 100644 --- a/DrissionPage/web_page.pyi +++ b/DrissionPage/web_page.pyi @@ -54,7 +54,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def mode(self) -> str: ... @property - def cookies(self)->Union[dict, list]: ... + def cookies(self) -> Union[dict, list]: ... @property def session(self) -> Session: ... @@ -74,6 +74,12 @@ class WebPage(SessionPage, ChromiumPage, BasePage): @property def _session_url(self) -> str: ... + @property + def timeout(self) -> float: ... + + @timeout.setter + def timeout(self, second: float) -> None: ... + def get(self, url: str, show_errmsg: bool = False, @@ -155,6 +161,6 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def _set_driver_options(self, driver_or_Options: Union[ChromiumDriver, DriverOptions]) -> None: ... - def _set_session_options(self, Session_or_Options:Union[Session, SessionOptions]) -> None: ... + def _set_session_options(self, Session_or_Options: Union[Session, SessionOptions]) -> None: ... def quit(self) -> None: ... diff --git a/docs/WebPage使用方法/3.10动作链.md b/docs/WebPage使用方法/3.10动作链.md index f76e3ca..ee8bd3a 100644 --- a/docs/WebPage使用方法/3.10动作链.md +++ b/docs/WebPage使用方法/3.10动作链.md @@ -32,13 +32,13 @@ from DrissionPage import ActionChains 创建动作链对象非常简单,只要把`WebPage`对象或`ChromiumPage`对象传入即可。动作链只在这个页面上生效。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | ------ | ---------------------------- | --- | ------------ | | `page` | `WebPage`对象或`ChromiumPage`对象 | 无 | 动作链要操作的浏览器页面 | -**示例:** +**◽ 示例:** ```python from DrissionPage import WebPage, ActionChains @@ -53,21 +53,21 @@ ac = ActionChains(page) 此方法用于移动鼠标到元素中点,或页面上的某个绝对坐标。可设置偏移量,当带偏移量时,偏移量相对于元素左上角坐标。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | ------------ | ----------------------------------------- | --- | --------------------------------------- | | `ele_or_loc` | `ChrmoiumElement`、`str`、`Tuple[int, int]` | 无 | 元素对象、文本定位符或绝对坐标,坐标为`tuple`(int, int) 形式 | | `offset_x` | `int` | 0 | x 轴偏移量,向右为正,向左为负 | | `offset_y` | `int` | 0 | y 轴偏移量,向下为正,向上为负 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | -**示例:** +**◽ 示例:** ```python ele = page('tag:a') @@ -78,20 +78,20 @@ ac.move_to(ele_or_loc=ele) # 使鼠标移动过到 ele 元素上 此方法用于使鼠标相对当前位置移动若干距离。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | ---------- | ----- | --- | ---------------- | | `offset_x` | `int` | 0 | x 轴偏移量,向右为正,向左为负 | | `offset_y` | `int` | 0 | y 轴偏移量,向下为正,向上为负 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | -**示例:** +**◽ 示例:** ```python ac.move(300, 0) # 鼠标向右移动 300 像素 @@ -101,19 +101,19 @@ ac.move(300, 0) # 鼠标向右移动 300 像素 此方法用于使鼠标相对当前位置向上移动若干距离。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | ------- | ----- | --- | -------- | | `pixel` | `int` | 无 | 鼠标移动的像素值 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | -**示例:** +**◽ 示例:** ```python ac.up(50) # 鼠标向上移动 50 像素 @@ -123,15 +123,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于使鼠标相对当前位置向下移动若干距离。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | ------- | ----- | --- | -------- | | `pixel` | `int` | 无 | 鼠标移动的像素值 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -139,15 +139,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于使鼠标相对当前位置向左移动若干距离。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | ------- | ----- | --- | -------- | | `pixel` | `int` | 无 | 鼠标移动的像素值 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -155,15 +155,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于使鼠标相对当前位置向右移动若干距离。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | ------- | ----- | --- | -------- | | `pixel` | `int` | 无 | 鼠标移动的像素值 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -173,15 +173,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于单击鼠标左键,单击前可先移动到元素上。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | -------- | ----------------------- | ------ | -------------- | | `on_ele` | `ChromiumElement`、`str` | `None` | 要点击的元素对象或文本定位符 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -189,15 +189,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于单击鼠标右键,单击前可先移动到元素上。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | -------- | ----------------------- | ------ | -------------- | | `on_ele` | `ChromiumElement`、`str` | `None` | 要点击的元素对象或文本定位符 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -205,15 +205,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于单击鼠标中键,单击前可先移动到元素上。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | -------- | ----------------------- | ------ | -------------- | | `on_ele` | `ChromiumElement`、`str` | `None` | 要点击的元素对象或文本定位符 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -221,15 +221,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于按住鼠标左键不放,按住前可先移动到元素上。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | -------- | ----------------------- | ------ | -------------- | | `on_ele` | `ChromiumElement`、`str` | `None` | 要按住的元素对象或文本定位符 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -237,15 +237,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于释放鼠标左键,释放前可先移动到元素上。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | -------- | ----------------------- | ------ | -------------- | | `on_ele` | `ChromiumElement`、`str` | `None` | 要释放的元素对象或文本定位符 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -253,15 +253,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于按住鼠标右键不放,按住前可先移动到元素上。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | -------- | ----------------------- | ------ | -------------- | | `on_ele` | `ChromiumElement`、`str` | `None` | 要按住的元素对象或文本定位符 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -269,15 +269,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于释放鼠标右键,释放前可先移动到元素上。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | -------- | ----------------------- | ------ | -------------- | | `on_ele` | `ChromiumElement`、`str` | `None` | 要释放的元素对象或文本定位符 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -285,15 +285,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于按住鼠标中键不放,按住前可先移动到元素上。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | -------- | ----------------------- | ------ | -------------- | | `on_ele` | `ChromiumElement`、`str` | `None` | 要按住的元素对象或文本定位符 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -301,15 +301,15 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于释放鼠标中键,释放前可先移动到元素上。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | -------- | ----------------------- | ------ | -------------- | | `on_ele` | `ChromiumElement`、`str` | `None` | 要释放的元素对象或文本定位符 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -319,17 +319,17 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于滚动鼠标滚轮,滚动前可先移动到元素上。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | -| --------- | ----------------------- | ------ | -------------- | -| `delta_x` | `int` | 0 | 滚轮 x 轴变化值 | -| `delta_y` | `str` | 0 | 滚轮 y 轴变化值 | -| `on_ele` | `ChromiumElement`、`str` | `None` | 要滚动的元素对象或文本定位符 | +| 名称 | 类型 | 默认 | 说明 | +| --------- | ----------------------- | ------ | ------------------- | +| `delta_x` | `int` | 0 | 滚轮 x 轴变化值,向右为正,向左为负 | +| `delta_y` | `str` | 0 | 滚轮 y 轴变化值,向下为正,向上为负 | +| `on_ele` | `ChromiumElement`、`str` | `None` | 要滚动的元素对象或文本定位符 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -339,19 +339,19 @@ ac.up(50) # 鼠标向上移动 50 像素 此方法用于按下键盘按键,特殊字符见 Keys。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | ----- | ----- | --- | ---- | | `key` | `str` | 无 | 按键键值 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | -**示例:** +**◽ 示例:** ```python from DrissionPage.keys import Keys @@ -363,15 +363,15 @@ ac.key_down(Keys.CTRL) # 按下 ctrl 键 此方法用于提起键盘按键,特殊字符见 Keys。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | ----- | ----- | --- | ---- | | `key` | `str` | 无 | 按键键值 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -379,15 +379,15 @@ ac.key_down(Keys.CTRL) # 按下 ctrl 键 此方法用于输入一段文本。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | ------ | ----- | --- | ------ | | `text` | `str` | 无 | 要输入的文本 | -**返回:** +**◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | @@ -397,19 +397,19 @@ ac.key_down(Keys.CTRL) # 按下 ctrl 键 此方法用于在动作链中插入停顿。 -**参数:** +**◽ 参数:** -| 名称 | 数据类型 | 默认值 | 说明 | +| 名称 | 类型 | 默认 | 说明 | | -------- | ------- | --- | ---- | | `second` | `float` | 无 | 等待秒数 | -**返回:** + **◽ 返回:** -| 数据类型 | 说明 | +| 类型 | 说明 | | -------------- | ------- | | `ActionChains` | 动作链对象本身 | -**示例:** +**◽ 示例:** ```python ac.wait(3) # 停顿 3 秒 diff --git a/docs/WebPage使用方法/3.1创建页面对象.md b/docs/WebPage使用方法/3.1创建页面对象.md index 68c2d37..0f17825 100644 --- a/docs/WebPage使用方法/3.1创建页面对象.md +++ b/docs/WebPage使用方法/3.1创建页面对象.md @@ -10,40 +10,7 @@ 这 3 种页面对象的使用逻辑是一致的,使用时可根据实际须要选择使用。 -# ✔️ 三种页面对象 - -## 📍 `WebPage` - -`WebPage`对象封装了常用的网页操作,并实现在浏览器和 requests 两种模式之间的切换。 - -**初始化参数:** - -- `mode`:初始化时模式,`'d'`或`'s'`,默认为`'d'` -- `timeout`:超时时间,s 模式时为连接时间,d 模式时为查找元素、处理弹出框、输入文本等超时时间 -- `driver_or_options`:`ChromiumDriver`对象或`DriverOptions`对象,为`None`时使用 ini 文件配置,为`False`时不读取 ini 文件 -- `session_or_options`:`Session`对象或`SessionOptions`对象,为`None`时使用 ini 文件配置,为`False`时不读取 ini 文件 - -## 📍 `ChromiumPage` - -`ChroumiumPage`对象纯粹用于操作浏览器,不能切换模式。一个该对象对应的是浏览器上一个标签页。 - -**初始化参数:** - -- `addr_driver_opts`:浏览器信息,可以是 '地址:端口'字符串、`ChromiumDriver`对象,或`DriverOptions`对象 - -- `tab_id`:要控制的标签页id,不指定默认为激活的 - -- `timeout`:总体超时时间 - -## 📍 `SessionPage` - -`SessionPage`对象纯粹用于收发数据包,不能切换模式,产生的元素对象为`SessionElement`。 - -**初始化参数:** - -- `session_or_options`:`Session`对象或`SessionOptions`对象 - -- `timeout`:连接超时时间 +!>**注意:**
如果有已经打开的同类型浏览器,请先关闭,或者按照下文“多浏览器共存”内容设置。否则会报错。 # ✔️ 直接创建 @@ -54,7 +21,7 @@ ```python # 默认以 d 模式创建页面对象 -page = WebPage('d') +page = WebPage() # 指定以 s 模式创建页面对象 page = WebPage('s') @@ -68,16 +35,18 @@ page = SessionPage() # ✔️ 通过配置信息创建 -本库有两种管理配置信息的对象,`DriverOptions`和`SessionOptions`,分别对应 d 模式和 s 模式的配置。须要时,可以创建相应的配置对象进行设置。 +本库有两种管理配置信息的对象,`DriverOptions`和`SessionOptions`,分别对应控制浏览器和收发数据包的配置。须要时,可以创建相应的配置对象进行设置。 -## 📍 `DriverOptions`类 +## 📍 `DriverOptions` `DriverOptions`用于管理创建浏览器时的配置,内置了常用的配置,并能实现链式操作。详细使用方法见“启动配置”一节。 -初始化参数: +**◽ 初始化参数:** -- read_file:是否从 ini 文件中读取配置信息 -- ini_path:ini 文件路径,为`None`则读取默认 ini 文件 +| 名称 | 类型 | 默认 | 说明 | +| ----------- | ------ | ------ | ------------------------ | +| `read_file` | `bool` | `True` | 是否从 ini 文件中读取配置信息 | +| `ini_path` | `str` | `None` | 文件路径,为`None`则读取默认 ini 文件 | !>**注意:**
浏览器创建后再修改这个配置是没有效果的。 @@ -91,49 +60,44 @@ do = DriverOptions().set_paths(chrome_path=r'D:\chrome.exe', local_port=9333) page = WebPage(driver_or_options=do) ``` -用 ChroumiumPage 创建页面对象 - -```python -page = ChromiumPage(addr_driver_opts=do) - -# 也可以直接把要控制的浏览器地址写在参数里 -page = ChromiumPage(addr_driver_opts='127.0.0.1:9333') -``` - -## 📍 `SessionOptions`类 +## 📍 `SessionOptions` `SessionOptions`用于管理创建`Session`对象时的配置,内置了常用的配置,并能实现链式操作。详细使用方法见“启动配置”一节。 -初始化参数: +**◽ 初始化参数:** -- read_file:是否从 ini 文件中读取配置信息 -- ini_path:ini 文件路径,为`None`则读取默认 ini 文件 +| 名称 | 类型 | 默认 | 说明 | +| ----------- | ------ | ------ | ------------------------ | +| `read_file` | `bool` | `True` | 是否从 ini 文件中读取配置信息 | +| `ini_path` | `str` | `None` | 文件路径,为`None`则读取默认 ini 文件 | !>**注意:**
`Session`对象创建后再修改这个配置是没有效果的。 ```python # 导入 SessionOptions -from DrissionPage import WebPage, SessionOptions +from DrissionPage import SessionPage, SessionOptions proxies = {'http': 'http://127.0.0.1:1080', - 'https': 'https://127.0.0.1:1080'} + 'https': 'http://127.0.0.1:1080'} # 创建配置对象,不从 ini 文件读取,并设置代理信息 so = SessionOptions(read_file=False).set_proxies(proxies) -# 用该配置创建页面对象(s 模式) -page = WebPage(mode='s', session_or_options=so) -``` - -用 SessionPage 创建页面对象 - -```python +# 用该配置创建页面对象 page = SessionPage(session_or_options=so) ``` -d 模式的配置和 s 模式的配置是可以同时使用的,不会互相影响。 +`WebPage`创建时浏览器配置和`Session`对象配置是可以同时使用的,不会互相影响。 ```python -page = WebPage(mode='s', session_or_options=so, driver_or_options=do) +page = WebPage(session_or_options=so, driver_or_options=do) +``` + +## 📍 直接指定地址创建 + +`ChromiumPage`可以直接接收浏览器地址来创建,格式为 'ip:port'。 + +```python +page = ChromiumPage(addr_driver_opts='127.0.0.1:9333') ``` ## 📍 使用其它 ini 文件创建 @@ -147,20 +111,41 @@ do = DriverOptinos(ini_path=r'./config1.ini') page = WebPage(driver_or_options=do) ``` -# ✔️ 传递驱动器 +# ✔️ 传递控制权 当须要使用多个页面对象共同操作一个页面时,可在对象间传递驱动器。 ```python from DrissionPage import WebPage +# 创建第一个页面 page1 = WebPage() +# 获取页面对象的浏览器控制器 driver = page1.driver +# 获取页面对象的Session对象 session = page1.session +# 把两个控制器对象在第二个页面对象初始化时传递进去 page2 = WebPage(driver_or_options=driver, session_or_options=session) ``` -# ✔️ 接管手动打开的浏览器 +# ✔️ 接管已打开的浏览器 + +页面对象创建时,只要指定的 ip:port 中已有浏览器在运行,就会直接接管。无论浏览器是下面哪种方式启动的。 + +## 📍 用程序启动的浏览器 + +默认情况下,创建浏览器页面对象时会自动启动一个浏览器。只要这个浏览器不关闭,下次运行程序时会接管同一个浏览器继续操作(配置的 ip:port 信息不变)。 + +这种方式极大地方便了程序的调试,使程序不必每次重新开始,可以单独调试某个功能。 + +```python +from DrissionPage import ChromiumPage + +# 创建对象同时启动浏览器,如果浏览器已经存在,则接管它 +page = ChromiumPage() +``` + +## 📍 手动打开的浏览器 如果须要手动打开浏览器再接管,可以这样做: @@ -170,13 +155,16 @@ page2 = WebPage(driver_or_options=driver, session_or_options=session) - 点击确定 -- 在程序中的浏览器配置中指定接管该端口浏览器,如下: +- 在程序中的浏览器配置中指定接管该端口浏览器 + +文件快捷方式的目标路径设置: ``` -# 文件快捷方式的目标路径设置 D:\chrome.exe --remote-debugging-port=9222 ``` +程序代码: + ```python from DrissionPage import WebPage, DriverOptions @@ -184,80 +172,108 @@ do = DriverOptions().set_paths(local_port=9222) page = WebPage(driver_or_options=do) ``` -?>**Tips:**
接管使用 bat 文件打开的浏览器也是一样做法做法。
接管浏览器时只有`local_port`、`debugger_address`参数是有效的。 +!> **注意:**
接管浏览器时只有`local_port`、`debugger_address`参数是有效的。 -# ✔️ 多 Chrome 浏览器共存 +## 📍 bat 文件启动的浏览器 -如果想要同时操作多个 Chrome 浏览器,或者自己在使用 Chrome 上网,同时控制另外几个跑自动化,就须要给这些被程序控制的浏览器设置单独的端口和用户文件夹,否则会造成冲突。具体用`DriverOptions`对象进行设置,示例如下: +可以把上一种方式的目标路径设置写进 bat 文件(Windows系统),运行 bat 文件来启动浏览器,再用程序接管。 + +新建一个文本文件,在里面输入以下内容(路径改为自己电脑的): + +```console +"D:\chrome.exe" --remote-debugging-port=9222 +``` + +保存后把后缀改成 bat,然后双击运行就能在 9222 端口启动一个浏览器。程序代码则和上一个方法一致。 + +# ✔️ 多浏览器共存 + +## 📍 用程序启动的浏览器 + +如果想要同时操作多个浏览器,或者自己在使用其中一个上网,同时控制另外几个跑自动化,就须要给这些被程序控制的浏览器设置单独的**端口**和**用户文件夹**,否则会造成冲突。具体用`DriverOptions`对象进行设置,示例如下: ```python -from DrissionPage import DriverOptions +from DrissionPage import ChromiumPage, DriverOptions do1 = DriverOptions().set_paths(local_port=9111, user_data_path=r'D:\data1') do2 = DriverOptions().set_paths(local_port=9222, user_data_path=r'D:\data2') -page1 = WebPage(driver_or_options=do1) -page2 = WebPage(driver_or_options=do2) +page1 = ChromiumPage(driver_or_options=do1) +page2 = ChromiumPage(driver_or_options=do2) page1.get('https://www.baidu.com') page2.get('http://www.163.com') ``` -如果要接管多个手动打开的浏览器,每个浏览器后面的参数都要添加`--remote-debugging-port`和`--user-data-dir`参数。示例如下: +?>**Tips:**
每个浏览器都要设置独立的端口号和用户文件夹,二者缺一不可。 + +## 📍 bat 文件启动的浏览器 + +如果要接管多个 bat 文件打开的浏览器,每个浏览器的参数都要添加`--remote-debugging-port`和`--user-data-dir`参数。浏览器路径则是一样的。示例如下: + +bat 文件1 ``` -# 浏览器1目标设置 -D:\chrome.exe --remote-debugging-port=9111 --user-data-dir=D:\data1 - -# 浏览器2目标设置 -D:\chrome.exe --remote-debugging-port=9222 --user-data-dir=D:\data2 +"D:\chrome.exe" --remote-debugging-port=9111 --user-data-dir=D:\data1 ``` +bat 文件2 + +``` +"D:\chrome.exe“ --remote-debugging-port=9222 --user-data-dir=D:\data2 +``` + +程序代码: + ```python -from DrissionPage import DriverOptions +from DrissionPage import ChromiumPage, DriverOptions do1 = DriverOptions().set_paths(local_port=9111) do2 = DriverOptions().set_paths(local_port=9222) -page1 = WebPage(driver_or_options=do1) -page2 = WebPage(driver_or_options=do2) +page1 = ChromiumPage(driver_or_options=do1) +page2 = ChromiumPage(driver_or_options=do2) ``` -?> **Tips:**
使用 bat 文件打开浏览器再接管操作是一样的。 +# ✔️ 页面对象初始化 API -# ✔️ 一些技巧 +## 📍 `ChromiumPage` -事实上,本库默认启动浏览器的方式是先通过程序在 9222(或用户指定的)端口运行一个浏览器进程,然后通过程序接管。这种做法有很多好处: +`ChroumiumPage`对象纯粹用于操作浏览器,不能切换模式。一个该对象对应的是浏览器上一个标签页。 -## 📍 可重复使用的浏览器对象 +**◽ 初始化参数:** -当程序运行完毕,浏览器不会主动关闭,下次再运行的时候可以直接在当前状态下继续运行。于是无须每次打开新的浏览器对象,无须从最开始步骤重新运行整个程序,一些前置条件(如登录)也无须每次运行,大大提高开发效率。 +| 名称 | 类型 | 默认 | 说明 | +| ------------------ | -------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------- | +| `addr_driver_opts` | `str`、`ChromiumDriver`、`DriverOptions` | `None` | 浏览器启动配置或接管信息;传入' ip:port' 字符串或`ChromiumDriver`时接管浏览器,传入`DriverOptions`时按配置启动浏览器,为`None`时使用配置文件配置启动浏览器 | +| `tab_id` | `str` | `None` | 要控制的标签页id,用于 d 模式,为`None`则控制激活的标签页 | +| `timeout` | `float` | `None` | 整体超时时间,为`None`则从配置文件中读取 | -## 📍 简便的调试方式 +## 📍 `SessionPage` -通过重复使用浏览器对象,用户可以把浏览器页面调整到某个状态再用程序接管,对调试某个特定问题效率极高。比如有些通过很多步骤才能到达的页面,如果每次重新运行会花费大量时间,而将页面固定再由程序接管,测试各种细节非常方便快捷。 +`SessionPage`对象纯粹用于收发数据包,不能切换模式,产生的元素对象为`SessionElement`。 -## 📍 一行代码传递登录状态到 requests +**◽ 初始化参数:** -本库的一个特点是打通了浏览器和`requests`之间的登录状态,我们可以手动登录浏览器,再用程序接管,然后切换到 s 模式,这时 s 模式的`Session`对象即已活动浏览器的登录信息,无须用`requests` -处理登录过程,极大地简化了开发复杂程度。示例: +| 名称 | 类型 | 默认 | 说明 | +| -------------------- | -------------------------- | ------ | --------------------------------------------------------------- | +| `session_or_options` | `Session`、`SessionOptions` | `None` | 传入`Session`对象时使用该对象收发数据包;传入`SessionOptions`对象时用该配置创建`Session`对象 | +| `timeout` | `float` | `None` | 连接超时时间, | -```python -# 假设已在 9222 端口打开了一个浏览器,并已登录某网站 -from DrissionPage import WebPage +## 📍 `WebPage` -page = WebPage() # 用 d 模式创建页面对象,默认接管 9222 端口 -page.change_mode() # 切换到 s 模式,即使用 requests 进行操作 -page.get('某url...') # 即可已登录状态访问 -``` +`WebPage`对象封装了常用的网页操作,并实现在浏览器和 requests 两种模式之间的切换。 -使用其它端口号: +**◽ 初始化参数:** -```python -from DrissionPage import WebPage, DriverOptions +| 名称 | 类型 | 默认 | 说明 | +| -------------------- | --------------------------------------- | ------ | ---------------------------------------------------------------- | +| `mode` | `str` | `'d'` | 启动时的模式,只能传入`'d'`或`'s'` | +| `timeout` | `float` | `None` | 整体超时时间,为`None`则从配置文件中读取 | +| `tab_id` | `str` | `None` | 要控制的标签页id,用于 d 模式,为`None`则控制激活的标签页 | +| `driver_or_options` | `ChromiumDriver`、`DriverOptions`、`bool` | `None` | 浏览器控制对象或浏览器启动配置对象;为`None`时使用 ini 文件配置;为`False`时不读取 ini 文件。 | +| `session_or_options` | `Session`、`SessionOptions`、`bool` | `None` | 收发数据包对象或`Session`启动配置对象;为`None`时使用 ini 文件配置;为`False`时不读取 ini 文件。 | -do = DriverOptions().set_paths(local_port=9333) -page = WebPage(driver_or_option=do) -page.change_mode() -page.get('某url...') -``` +**◽ 说明:** + +`driver_or_options`和`session_or_options`传入`ChromiumDriver`和`Session`对象时,可在多个页面对象间传递控制权。 diff --git a/docs/版本历史.md b/docs/版本历史.md index 930a42e..b2239d4 100644 --- a/docs/版本历史.md +++ b/docs/版本历史.md @@ -1,12 +1,15 @@ -# v3.0.32 +# v3.0.33 - `WebPage`删除`check_page()`方法 - `DriverOptions`和`easy_set`的`set_paths()`增加`browser_path`参数 - `DriverOptions`增加`browser_path`属性 - `ChromiumFrame`现在支持页面滚动 -- 修改`SessionElement`相对定位参数顺序 - 改进滚动到元素功能 -- 修复一些问题 +- 修改`SessionElement`相对定位参数顺序 +- `SessionPage`也可以从 ini 文件读取 timeout 设置 +- ini 文件中`session_options`增加`timeout`项 +- `SessionOptions`增加`timeout`属性 +- 优化和修复一些问题 # v3.0.31 diff --git a/setup.py b/setup.py index 8be14a3..45a505c 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ with open("README.md", "r", encoding='utf-8') as fh: setup( name="DrissionPage", - version="3.0.32", + version="3.0.33", author="g1879", author_email="g1879@qq.com", description="A module that integrates selenium and requests session, encapsulates common page operations.",