input()前自动等待元素可点击;修改ElementsList,未完成

This commit is contained in:
g1879 2024-06-14 11:37:53 +08:00
parent 40dd6290d1
commit e9c50c2efe
8 changed files with 133 additions and 74 deletions

View File

@ -14,4 +14,4 @@ from ._configs.chromium_options import ChromiumOptions
from ._configs.session_options import SessionOptions from ._configs.session_options import SessionOptions
__all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__'] __all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__']
__version__ = '4.0.4.24' __version__ = '4.0.4.25'

View File

@ -637,6 +637,7 @@ class ChromiumElement(DrissionElement):
self.run_js('this.dispatchEvent(new Event("change", {bubbles: true}));') self.run_js('this.dispatchEvent(new Event("change", {bubbles: true}));')
return return
self.wait.clickable(timeout=.5)
if clear and vals not in ('\n', '\ue007'): if clear and vals not in ('\n', '\ue007'):
self.clear(by_js=False) self.clear(by_js=False)
else: else:
@ -703,7 +704,6 @@ class ChromiumElement(DrissionElement):
ele_or_loc = ele_or_loc.rect.midpoint ele_or_loc = ele_or_loc.rect.midpoint
elif not isinstance(ele_or_loc, (list, tuple)): elif not isinstance(ele_or_loc, (list, tuple)):
raise TypeError('需要ChromiumElement对象或坐标。') raise TypeError('需要ChromiumElement对象或坐标。')
self.owner.actions.hold(self).move_to(ele_or_loc, duration=duration).release() self.owner.actions.hold(self).move_to(ele_or_loc, duration=duration).release()
def _get_obj_id(self, node_id=None, backend_id=None): def _get_obj_id(self, node_id=None, backend_id=None):

View File

@ -10,6 +10,11 @@ from ..errors import ElementNotFoundError
class NoneElement(object): class NoneElement(object):
def __init__(self, page=None, method=None, args=None): def __init__(self, page=None, method=None, args=None):
"""
:param page:
:param method:
:param args:
"""
if page: if page:
self._none_ele_value = page._none_ele_value self._none_ele_value = page._none_ele_value
self._none_ele_return_value = page._none_ele_return_value self._none_ele_return_value = page._none_ele_return_value

View File

@ -13,6 +13,7 @@ from threading import Lock
from time import perf_counter, sleep from time import perf_counter, sleep
from .._configs.options_manage import OptionsManager from .._configs.options_manage import OptionsManager
from .._elements.none_element import NoneElement
from ..errors import (ContextLostError, ElementLostError, CDPError, PageDisconnectedError, NoRectError, from ..errors import (ContextLostError, ElementLostError, CDPError, PageDisconnectedError, NoRectError,
AlertExistsError, WrongURLError, StorageError, CookieFormatError, JavaScriptError) AlertExistsError, WrongURLError, StorageError, CookieFormatError, JavaScriptError)
@ -235,91 +236,141 @@ def raise_error(result, ignore=None):
class ElementsList(list): class ElementsList(list):
def displayed(self): # def __init__(self, page=None, method=None, ):
"""返回所有显示的元素""" # super().__init__()
return self._any_state('is_displayed')
def hidden(self): def displayed(self, get_all=False):
"""返回所有不显示的元素""" """返回显示的元素,默认返回第一个
return self._any_state('is_displayed', True) :param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
return self._any_state('is_displayed', get_all=get_all)
def checked(self): def hidden(self, get_all=False):
"""返回所有被选中的元素""" """返回不显示的元素,默认返回第一个
return self._any_state('is_checked') :param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
return self._any_state('is_displayed', True, get_all=get_all)
def not_checked(self): def checked(self, get_all=False):
"""返回所有没被选中的元素""" """返回被选中的元素,默认返回第一个
return self._any_state('is_checked', True) :param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
return self._any_state('is_checked', get_all=get_all)
def selected(self): def not_checked(self, get_all=False):
"""返回所有被选中的列表元素""" """返回没被选中的元素"""
return self._any_state('is_selected') return self._any_state('is_checked', True, get_all=get_all)
def not_selected(self): def selected(self, get_all=False):
"""返回所有没被选中的列表元素""" """返回被选中的列表元素,默认返回第一个
return self._any_state('is_selected', True) :param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
return self._any_state('is_selected', get_all=get_all)
def enabled(self): def not_selected(self, get_all=False):
"""返回所有有效的元素""" """返回没被选中的列表元素,默认返回第一个
return self._any_state('is_enabled') :param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
return self._any_state('is_selected', True, get_all=get_all)
def disabled(self): def enabled(self, get_all=False):
"""返回所有无效的元素""" """返回有效的元素,默认返回第一个
return self._any_state('is_enabled', True) :param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
return self._any_state('is_enabled', get_all=get_all)
def clickable(self): def disabled(self, get_all=False):
"""返回所有可被点击的元素""" """返回无效的元素,默认返回第一个
return self._any_state('is_clickable') :param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
return self._any_state('is_enabled', True, get_all=get_all)
def not_clickable(self): def clickable(self, get_all=False):
"""返回所有不可被点击的元素""" """返回可被点击的元素,默认返回第一个
return self._any_state('is_clickable', True) :param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
return self._any_state('is_clickable', get_all=get_all)
def has_rect(self): def not_clickable(self, get_all=False):
"""返回所有有大小和位置的元素""" """返回不可被点击的元素,默认返回第一个
return self._any_state('has_rect') :param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
return self._any_state('is_clickable', True, get_all=get_all)
def no_rect(self): def have_rect(self, get_all=False):
"""返回所有没有大小和位置的元素""" """返回有大小和位置的元素,默认返回第一个
return self._any_state('has_rect', True) :param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
return self._any_state('has_rect', get_all=get_all)
def style(self, name, value): def no_rect(self, get_all=False):
"""返回所有拥有某个style值的元素 """返回没有大小和位置的元素,默认返回第一个
:param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
return self._any_state('has_rect', True, get_all=get_all)
def have_text(self, get_all=False):
"""返回包含文本的元素,默认返回第一个
:param get_all: 是否返回所有
:return: 元素或元素组成的列表
"""
r = ElementsList()
for i in self:
if i.raw_text:
r.append(i)
return r if get_all else r[0] if r else NoneElement()
def style(self, name, value, get_all=False):
"""返回拥有某个style值的元素默认返回第一个
:param name: 属性名称 :param name: 属性名称
:param value: 属性值 :param value: 属性值
:param get_all: 是否返回所有
:return: 筛选结果 :return: 筛选结果
""" """
r = ElementsList() r = ElementsList()
for i in self: for i in self:
if i.style(name) == value: if i.style(name) == value:
r.append(i) r.append(i)
return r return r if get_all else r[0] if r else NoneElement()
def property(self, name, value): def property(self, name, value, get_all=False):
"""返回所有拥有某个property值的元素 """返回拥有某个property值的元素,默认返回第一个
:param name: 属性名称 :param name: 属性名称
:param value: 属性值 :param value: 属性值
:param get_all: 是否返回所有
:return: 筛选结果 :return: 筛选结果
""" """
r = ElementsList() r = ElementsList()
for i in self: for i in self:
if i.property(name) == value: if i.property(name) == value:
r.append(i) r.append(i)
return r return r if get_all else r[0] if r else NoneElement()
def attr(self, name, value): def attr(self, name, value, get_all=False):
"""返回所有拥有某个attribute值的元素 """返回拥有某个attribute值的元素,默认返回第一个
:param name: 属性名称 :param name: 属性名称
:param value: 属性值 :param value: 属性值
:param get_all: 是否返回所有
:return: 筛选结果 :return: 筛选结果
""" """
r = ElementsList() r = ElementsList()
for i in self: for i in self:
if i.attr(name) == value: if i.attr(name) == value:
r.append(i) r.append(i)
return r return r if get_all else r[0] if r else NoneElement()
def _any_state(self, name, is_not=False): def _any_state(self, name, is_not=False, get_all=False):
""" """
:param name: 状态名称 :param name: 状态名称
:param is_not: 是否选择否定的 :param is_not: 是否选择否定的
@ -334,4 +385,4 @@ class ElementsList(list):
for i in self: for i in self:
if getattr(i.states, name): if getattr(i.states, name):
r.append(i) r.append(i)
return r return r if get_all else r[0] if r else NoneElement()

View File

@ -50,34 +50,38 @@ def raise_error(result: dict, ignore=None) -> None: ...
class ElementsList(list): class ElementsList(list):
def displayed(self) -> List[ChromiumElement]: ... def displayed(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def hidden(self) -> List[ChromiumElement]: ... def hidden(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def checked(self) -> List[ChromiumElement]: ... def checked(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def not_checked(self) -> List[ChromiumElement]: ... def not_checked(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def selected(self) -> List[ChromiumElement]: ... def selected(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def not_selected(self) -> List[ChromiumElement]: ... def not_selected(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def enabled(self) -> List[ChromiumElement]: ... def enabled(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def disabled(self) -> List[ChromiumElement]: ... def disabled(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def clickable(self) -> List[ChromiumElement]: ... def clickable(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def not_clickable(self) -> List[ChromiumElement]: ... def not_clickable(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def has_rect(self) -> List[ChromiumElement]: ... def have_rect(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def no_rect(self) -> List[ChromiumElement]: ... def no_rect(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def style(self, name: str, value: str) -> List[ChromiumElement]: ... def have_text(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def property(self, name: str, value: str) -> List[ChromiumElement]: ... def style(self, name: str, value: str, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def attr(self, name: str, value: str) -> List[ChromiumElement]: ... def property(self, name: str, value: str, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def _any_state(self, name: str, is_not: bool = False) -> List[ChromiumElement]: ... def attr(self, name: str, value: str, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def _any_state(self, name: str, is_not: bool = False, get_all: bool = False) -> List[ChromiumElement]: ...
def __next__(self) -> ChromiumElement: ...

View File

@ -141,7 +141,7 @@ class Actions:
:return: self :return: self
""" """
if on_ele: if on_ele:
self.move_to(on_ele, duration=0) self.move_to(on_ele, duration=.2)
self._release('left') self._release('left')
return self return self
@ -159,7 +159,7 @@ class Actions:
:return: self :return: self
""" """
if on_ele: if on_ele:
self.move_to(on_ele, duration=0) self.move_to(on_ele, duration=.2)
self._release('right') self._release('right')
return self return self
@ -177,7 +177,7 @@ class Actions:
:return: self :return: self
""" """
if on_ele: if on_ele:
self.move_to(on_ele, duration=0) self.move_to(on_ele, duration=.2)
self._release('middle') self._release('middle')
return self return self
@ -189,7 +189,7 @@ class Actions:
:return: self :return: self
""" """
if on_ele: if on_ele:
self.move_to(on_ele, duration=0) self.move_to(on_ele, duration=.2)
self._dr.run('Input.dispatchMouseEvent', type='mousePressed', button=button, clickCount=count, self._dr.run('Input.dispatchMouseEvent', type='mousePressed', button=button, clickCount=count,
x=self.curr_x, y=self.curr_y, modifiers=self.modifier) x=self.curr_x, y=self.curr_y, modifiers=self.modifier)
self._holding = button self._holding = button
@ -213,7 +213,7 @@ class Actions:
:return: self :return: self
""" """
if on_ele: if on_ele:
self.move_to(on_ele, duration=0) self.move_to(on_ele, duration=.2)
self._dr.run('Input.dispatchMouseEvent', type='mouseWheel', x=self.curr_x, y=self.curr_y, self._dr.run('Input.dispatchMouseEvent', type='mouseWheel', x=self.curr_x, y=self.curr_y,
deltaX=delta_x, deltaY=delta_y, modifiers=self.modifier) deltaX=delta_x, deltaY=delta_y, modifiers=self.modifier)
return self return self

View File

@ -204,7 +204,6 @@ class Clicker(object):
""" """
self._ele.owner.run_cdp('Input.dispatchMouseEvent', type='mousePressed', x=client_x, self._ele.owner.run_cdp('Input.dispatchMouseEvent', type='mousePressed', x=client_x,
y=client_y, button=button, clickCount=count, _ignore=AlertExistsError) y=client_y, button=button, clickCount=count, _ignore=AlertExistsError)
# sleep(.05)
self._ele.owner.run_cdp('Input.dispatchMouseEvent', type='mouseReleased', x=client_x, self._ele.owner.run_cdp('Input.dispatchMouseEvent', type='mouseReleased', x=client_x,
y=client_y, button=button, _ignore=AlertExistsError) y=client_y, button=button, _ignore=AlertExistsError)

View File

@ -251,13 +251,13 @@ class Listener(object):
self._target_id = target_id self._target_id = target_id
self._address = address self._address = address
self._owner = owner self._owner = owner
debug = False # debug = False
if self._driver: if self._driver:
debug = self._driver._debug # debug = self._driver._debug
self._driver.stop() self._driver.stop()
if self.listening: if self.listening:
self._driver = Driver(self._target_id, 'page', self._address) self._driver = Driver(self._target_id, 'page', self._address)
self._driver._debug = debug # self._driver._debug = debug
self._driver.run('Network.enable') self._driver.run('Network.enable')
self._set_callback() self._set_callback()