修复drag()方法定位不准问题;位置和大小改为以tuple方式返回;完善make_session_ele();改进类型注解

This commit is contained in:
g1879 2022-12-21 17:46:30 +08:00
parent 0e0e34868e
commit 3a2d0c9f18
8 changed files with 129 additions and 131 deletions

View File

@ -30,9 +30,9 @@ class ActionChains:
lx = ele_or_loc[0] + offset_x lx = ele_or_loc[0] + offset_x
ly = ele_or_loc[1] + offset_y ly = ele_or_loc[1] + offset_y
elif 'ChromiumElement' in str(type(ele_or_loc)): elif 'ChromiumElement' in str(type(ele_or_loc)):
ele_loc = ele_or_loc.location if offset_x or offset_y else ele_or_loc.midpoint x, y = ele_or_loc.location if offset_x or offset_y else ele_or_loc.midpoint
lx = ele_loc['x'] + offset_x lx = x + offset_x
ly = ele_loc['y'] + offset_y ly = y + offset_y
else: else:
raise TypeError('ele_or_loc参数只能接受坐标(x, y)或ChromiumElement对象。') raise TypeError('ele_or_loc参数只能接受坐标(x, y)或ChromiumElement对象。')

View File

@ -18,33 +18,33 @@ class ActionChains:
self.modifier: int = ... self.modifier: int = ...
def move_to(self, ele_or_loc: Union[ChromiumElement, Tuple[int, int]], def move_to(self, ele_or_loc: Union[ChromiumElement, Tuple[int, int]],
offset_x: int = ..., offset_y: int = ...) -> 'ActionChains': ... offset_x: int = ..., offset_y: int = ...) -> ActionChains: ...
def move(self, offset_x: int = ..., offset_y: int = ...) -> 'ActionChains': ... def move(self, offset_x: int = ..., offset_y: int = ...) -> ActionChains: ...
def hold(self, on_ele:ChromiumElement=...) -> 'ActionChains': ... def hold(self, on_ele:ChromiumElement=...) -> ActionChains: ...
def click(self, on_ele:ChromiumElement=...) -> 'ActionChains': ... def click(self, on_ele:ChromiumElement=...) -> ActionChains: ...
def r_click(self, on_ele:ChromiumElement=...) -> 'ActionChains': ... def r_click(self, on_ele:ChromiumElement=...) -> ActionChains: ...
def release(self, on_ele:ChromiumElement=...) -> 'ActionChains': ... def release(self, on_ele:ChromiumElement=...) -> ActionChains: ...
def scroll(self, delta_x: int = ..., delta_y: int = ..., on_ele:ChromiumElement=...) -> 'ActionChains': ... def scroll(self, delta_x: int = ..., delta_y: int = ..., on_ele:ChromiumElement=...) -> ActionChains: ...
def up(self, pixel: int) -> 'ActionChains': ... def up(self, pixel: int) -> ActionChains: ...
def down(self, pixel: int) -> 'ActionChains': ... def down(self, pixel: int) -> ActionChains: ...
def left(self, pixel: int) -> 'ActionChains': ... def left(self, pixel: int) -> ActionChains: ...
def right(self, pixel: int) -> 'ActionChains': ... def right(self, pixel: int) -> ActionChains: ...
def key_down(self, key:str) -> 'ActionChains': ... def key_down(self, key:str) -> ActionChains: ...
def key_up(self, key:str) -> 'ActionChains': ... def key_up(self, key:str) -> ActionChains: ...
def wait(self, second: float) -> 'ActionChains': ... def wait(self, second: float) -> ActionChains: ...
def _get_key_data(self, key:str, action: str) -> dict: ... def _get_key_data(self, key:str, action: str) -> dict: ...

View File

@ -2,20 +2,17 @@
""" """
@Author : g1879 @Author : g1879
@Contact : g1879@qq.com @Contact : g1879@qq.com
@File : chromium_element.py
""" """
from os import sep from os import sep
from os.path import basename from os.path import basename
from pathlib import Path from pathlib import Path
from re import search from re import search
from time import perf_counter, sleep from time import perf_counter, sleep
from urllib.parse import urlparse
from .base import DrissionElement, BaseElement from .base import DrissionElement, BaseElement
from .common import make_absolute_link, get_loc, get_ele_txt, format_html, is_js_func, _location_in_viewport from .common import make_absolute_link, get_loc, get_ele_txt, format_html, is_js_func, _location_in_viewport
from .keys import _keys_to_typing, _keyDescriptionForString, _keyDefinitions from .keys import _keys_to_typing, _keyDescriptionForString, _keyDefinitions
from .session_element import make_session_ele from .session_element import make_session_ele
from .chromium_frame import ChromiumFrame
class ChromiumElement(DrissionElement): class ChromiumElement(DrissionElement):
@ -61,7 +58,8 @@ class ChromiumElement(DrissionElement):
def tag(self): def tag(self):
"""返回元素tag""" """返回元素tag"""
if self._tag is None: if self._tag is None:
self._tag = self.page.run_cdp('DOM.describeNode', nodeId=self._node_id)['node']['localName'].lower() self._tag = self.page.run_cdp('DOM.describeNode', nodeId=self._node_id, not_change=True)['node'][
'localName'].lower()
return self._tag return self._tag
@property @property
@ -69,11 +67,11 @@ class ChromiumElement(DrissionElement):
"""返回元素outerHTML文本""" """返回元素outerHTML文本"""
tag = self.tag tag = self.tag
if tag in ('iframe', 'frame'): if tag in ('iframe', 'frame'):
out_html = self.page.run_cdp('DOM.getOuterHTML', nodeId=self._node_id)['outerHTML'] out_html = self.page.run_cdp('DOM.getOuterHTML', nodeId=self._node_id, not_change=True)['outerHTML']
in_html = self.inner_html in_html = self.inner_html
sign = search(rf'<{tag}.*?>', out_html).group(0) sign = search(rf'<{tag}.*?>', out_html).group(0)
return f'{sign}{in_html}</{tag}>' return f'{sign}{in_html}</{tag}>'
return self.page.run_cdp('DOM.getOuterHTML', nodeId=self._node_id)['outerHTML'] return self.page.run_cdp('DOM.getOuterHTML', nodeId=self._node_id, not_change=True)['outerHTML']
@property @property
def inner_html(self): def inner_html(self):
@ -86,7 +84,7 @@ class ChromiumElement(DrissionElement):
@property @property
def attrs(self): def attrs(self):
"""返回元素所有attribute属性""" """返回元素所有attribute属性"""
attrs = self.page.run_cdp('DOM.getAttributes', nodeId=self._node_id)['attributes'] attrs = self.page.run_cdp('DOM.getAttributes', nodeId=self._node_id, not_change=True)['attributes']
attrs_len = len(attrs) attrs_len = len(attrs)
return {attrs[i]: attrs[i + 1] for i in range(0, attrs_len, 2)} return {attrs[i]: attrs[i + 1] for i in range(0, attrs_len, 2)}
@ -120,51 +118,51 @@ class ChromiumElement(DrissionElement):
def size(self): def size(self):
"""返回元素宽和高""" """返回元素宽和高"""
try: try:
model = self.page.run_cdp('DOM.getBoxModel', nodeId=self._node_id)['model'] model = self.page.run_cdp('DOM.getBoxModel', nodeId=self._node_id, not_change=True)['model']
return {'height': model['height'], 'width': model['width']} return model['height'], model['width']
except Exception: except Exception:
return {'height': 0, 'width': 0} return 0, 0
@property @property
def client_location(self): def client_location(self):
"""返回元素左上角在视口中的坐标""" """返回元素左上角在视口中的坐标"""
m = self._get_client_rect('border') m = self._get_client_rect('border')
return {'x': m[0], 'y': m[1]} if m else None return (m[0], m[1]) if m else (0, 0)
@property @property
def client_midpoint(self): def client_midpoint(self):
"""返回元素中间点在视口中的坐标""" """返回元素中间点在视口中的坐标"""
m = self._get_client_rect('border') m = self._get_client_rect('border')
return {'x': m[2] - m[0], 'y': m[5] - m[1]} if m else None return (m[0] + (m[2] - m[0]) // 2, m[3] + (m[5] - m[3]) // 2) if m else (0, 0)
@property @property
def location(self): def location(self):
"""返回元素左上角的绝对坐标""" """返回元素左上角的绝对坐标"""
cl = self.client_location cl = self.client_location
return self._get_absolute_rect(cl['x'], cl['y']) if cl else None return self._get_absolute_rect(cl[0], cl[1]) if cl else (0, 0)
@property @property
def midpoint(self): def midpoint(self):
"""返回元素中间点的绝对坐标""" """返回元素中间点的绝对坐标"""
cl = self.client_midpoint cl = self.client_midpoint
return self._get_absolute_rect(cl['x'], cl['y']) if cl else None return self._get_absolute_rect(cl[0], cl[1]) if cl else (0, 0)
@property @property
def _client_click_point(self): def _client_click_point(self):
"""返回元素左上角可接受点击的点视口坐标""" """返回元素左上角可接受点击的点视口坐标"""
m = self._get_client_rect('padding') m = self._get_client_rect('padding')
return {'x': m[0], 'y': m[1]} if m else None return (m[0], m[1]) if m else (0, 0)
@property @property
def _click_point(self): def _click_point(self):
"""返回元素左上角可接受点击的点的绝对坐标""" """返回元素左上角可接受点击的点的绝对坐标"""
cl = self._client_click_point cl = self._client_click_point
return self._get_absolute_rect(cl['x'], cl['y']) if cl else None return self._get_absolute_rect(cl[0], cl[1]) if cl else (0, 0)
@property @property
def shadow_root(self): def shadow_root(self):
"""返回当前元素的shadow_root元素对象""" """返回当前元素的shadow_root元素对象"""
info = self.page.run_cdp('DOM.describeNode', nodeId=self.node_id)['node'] info = self.page.run_cdp('DOM.describeNode', nodeId=self.node_id, not_change=True)['node']
if not info.get('shadowRoots', None): if not info.get('shadowRoots', None):
return None return None
@ -307,8 +305,8 @@ class ChromiumElement(DrissionElement):
@property @property
def is_in_viewport(self): def is_in_viewport(self):
"""返回元素是否出现在视口中,以元素可以接受点击的点为判断""" """返回元素是否出现在视口中,以元素可以接受点击的点为判断"""
loc = self.location x, y = self.location
return _location_in_viewport(self.page, loc['x'], loc['y']) if loc else False return _location_in_viewport(self.page, x, y) if x else False
def attr(self, attr): def attr(self, attr):
"""返回attribute属性值 \n """返回attribute属性值 \n
@ -361,7 +359,7 @@ class ChromiumElement(DrissionElement):
:param prop: 属性名 :param prop: 属性名
:return: 属性值文本 :return: 属性值文本
""" """
p = self.page.run_cdp('Runtime.getProperties', objectId=self._obj_id)['result'] p = self.page.run_cdp('Runtime.getProperties', objectId=self._obj_id, not_change=True)['result']
for i in p: for i in p:
if i['name'] == prop: if i['name'] == prop:
if 'value' not in i or 'value' not in i['value']: if 'value' not in i or 'value' not in i['value']:
@ -392,7 +390,7 @@ class ChromiumElement(DrissionElement):
:param args: 参数按顺序在js文本中对应argument[0]argument[2]... :param args: 参数按顺序在js文本中对应argument[0]argument[2]...
:return: 运行的结果 :return: 运行的结果
""" """
return run_script(self, script, as_expr, self.page.timeouts.script, args) return run_script(self, script, as_expr, self.page.timeouts.script, args, True)
def run_async_script(self, script, as_expr=False, *args): def run_async_script(self, script, as_expr=False, *args):
"""以异步方式执行js代码 \n """以异步方式执行js代码 \n
@ -402,7 +400,7 @@ class ChromiumElement(DrissionElement):
:return: None :return: None
""" """
from threading import Thread from threading import Thread
Thread(target=run_script, args=(self, script, as_expr, self.page.timeouts.script, args)).start() Thread(target=run_script, args=(self, script, as_expr, self.page.timeouts.script, args, True)).start()
def ele(self, loc_or_str, timeout=None): def ele(self, loc_or_str, timeout=None):
"""返回当前元素下级符合条件的第一个元素、属性或节点文本 \n """返回当前元素下级符合条件的第一个元素、属性或节点文本 \n
@ -472,7 +470,7 @@ class ChromiumElement(DrissionElement):
while not self.run_script(js) and perf_counter() < end_time: while not self.run_script(js) and perf_counter() < end_time:
sleep(.1) sleep(.1)
node = self.page.run_cdp('DOM.describeNode', nodeId=self._node_id)['node'] node = self.page.run_cdp('DOM.describeNode', nodeId=self._node_id, not_change=True)['node']
frame = node.get('frameId', None) frame = node.get('frameId', None)
frame = frame or self.page.tab_id frame = frame or self.page.tab_id
try: try:
@ -519,8 +517,8 @@ class ChromiumElement(DrissionElement):
while not self.run_script(js) and perf_counter() < end_time: while not self.run_script(js) and perf_counter() < end_time:
sleep(.1) sleep(.1)
left, top = self.location.values() left, top = self.location
height, width = self.size.values() height, width = self.size
left_top = (left, top) left_top = (left, top)
right_bottom = (left + width, top + height) right_bottom = (left + width, top + height)
return self.page.get_screenshot(path, as_bytes=as_bytes, full_page=False, return self.page.get_screenshot(path, as_bytes=as_bytes, full_page=False,
@ -536,7 +534,7 @@ class ChromiumElement(DrissionElement):
return self._set_file_input(vals) return self._set_file_input(vals)
try: try:
self.page.run_cdp('DOM.focus', nodeId=self._node_id) self.page.run_cdp('DOM.focus', nodeId=self._node_id, not_change=True)
except Exception: except Exception:
self.click(by_js=True) self.click(by_js=True)
@ -566,7 +564,7 @@ class ChromiumElement(DrissionElement):
""" """
if isinstance(files, str): if isinstance(files, str):
files = files.split('\n') files = files.split('\n')
self.page.run_cdp('DOM.setFileInputFiles', files=files, nodeId=self._node_id) self.page.run_cdp('DOM.setFileInputFiles', files=files, nodeId=self._node_id, not_change=True)
def clear(self, by_js=False): def clear(self, by_js=False):
"""清空元素文本 \n """清空元素文本 \n
@ -604,13 +602,9 @@ class ChromiumElement(DrissionElement):
if not by_js: if not by_js:
self.page.scroll_to_see(self) self.page.scroll_to_see(self)
if self.is_in_viewport: if self.is_in_viewport:
client_point = self._client_click_point client_x, client_y = self._client_click_point
if client_point: if client_x:
loc_point = self._click_point loc_x, loc_y = self._click_point
client_x = client_point['x']
client_y = client_point['y']
loc_x = loc_point['x']
loc_y = loc_point['y']
click = do_it(client_x, client_y, loc_x, loc_y) click = do_it(client_x, client_y, loc_x, loc_y)
if click: if click:
@ -643,8 +637,8 @@ class ChromiumElement(DrissionElement):
def r_click(self): def r_click(self):
"""右键单击""" """右键单击"""
self.page.scroll_to_see(self) self.page.scroll_to_see(self)
xy = self._client_click_point x, y = self._client_click_point
self._click(xy['x'], xy['y'], 'right') self._click(x, y, 'right')
def r_click_at(self, offset_x=None, offset_y=None): def r_click_at(self, offset_x=None, offset_y=None):
"""带偏移量右键单击本元素相对于左上角坐标。不传入x或y值时点击元素中点 \n """带偏移量右键单击本元素相对于左上角坐标。不传入x或y值时点击元素中点 \n
@ -683,9 +677,9 @@ class ChromiumElement(DrissionElement):
:param shake: 是否随机抖动 :param shake: 是否随机抖动
:return: None :return: None
""" """
curr_xy = self.midpoint curr_x, curr_y = self.midpoint
offset_x += curr_xy['x'] offset_x += curr_x
offset_y += curr_xy['y'] offset_y += curr_y
self.drag_to((offset_x, offset_y), speed, shake) self.drag_to((offset_x, offset_y), speed, shake)
def drag_to(self, ele_or_loc, speed=40, shake=True): def drag_to(self, ele_or_loc, speed=40, shake=True):
@ -697,17 +691,13 @@ class ChromiumElement(DrissionElement):
""" """
# x, y目标点坐标 # x, y目标点坐标
if isinstance(ele_or_loc, ChromiumElement): if isinstance(ele_or_loc, ChromiumElement):
midpoint = ele_or_loc.midpoint target_x, target_y = ele_or_loc.midpoint
target_x = midpoint['x']
target_y = midpoint['y']
elif isinstance(ele_or_loc, (list, tuple)): elif isinstance(ele_or_loc, (list, tuple)):
target_x, target_y = ele_or_loc target_x, target_y = ele_or_loc
else: else:
raise TypeError('需要ChromiumElement对象或坐标。') raise TypeError('需要ChromiumElement对象或坐标。')
curr_xy = self.midpoint current_x, current_y = self.midpoint
current_x = curr_xy['x']
current_y = curr_xy['y']
width = target_x - current_x width = target_x - current_x
height = target_y - current_y height = target_y - current_y
num = 0 if not speed else int(((abs(width) ** 2 + abs(height) ** 2) ** .5) // speed) num = 0 if not speed else int(((abs(width) ** 2 + abs(height) ** 2) ** .5) // speed)
@ -735,14 +725,14 @@ class ChromiumElement(DrissionElement):
:param node_id: cdp中的node id :param node_id: cdp中的node id
:return: js中的object id :return: js中的object id
""" """
return self.page.run_cdp('DOM.resolveNode', nodeId=node_id)['object']['objectId'] return self.page.run_cdp('DOM.resolveNode', nodeId=node_id, not_change=True)['object']['objectId']
def _get_node_id(self, obj_id): def _get_node_id(self, obj_id):
"""根据传入object id获取cdp中的node id \n """根据传入object id获取cdp中的node id \n
:param obj_id: js中的object id :param obj_id: js中的object id
:return: cdp中的node id :return: cdp中的node id
""" """
return self.page.run_cdp('DOM.requestNode', objectId=obj_id)['nodeId'] return self.page.run_cdp('DOM.requestNode', objectId=obj_id, not_change=True)['nodeId']
def _get_ele_path(self, mode): def _get_ele_path(self, mode):
"""返获取css路径或xpath路径""" """返获取css路径或xpath路径"""
@ -787,12 +777,12 @@ class ChromiumElement(DrissionElement):
return f':root{t}' if mode == 'css' else t return f':root{t}' if mode == 'css' else t
def _get_client_rect(self, quad): def _get_client_rect(self, quad):
"""按照类型返回坐标 """按照类型返回窗口坐标 \n
:param quad: 方框类型margin border padding :param quad: 方框类型margin border padding
:return: 四个角坐标大小为0时返回None :return: 四个角坐标大小为0时返回None
""" """
try: try:
return self.page.run_cdp('DOM.getBoxModel', nodeId=self.node_id)['model'][quad] return self.page.run_cdp('DOM.getBoxModel', nodeId=self.node_id, not_change=True)['model'][quad]
except: except:
return None return None
@ -845,7 +835,7 @@ class ChromiumShadowRootElement(BaseElement):
def is_alive(self): def is_alive(self):
"""返回元素是否仍在DOM中""" """返回元素是否仍在DOM中"""
try: try:
self.page.run_cdp('DOM.describeNode', nodeId=self._node_id) self.page.run_cdp('DOM.describeNode', nodeId=self._node_id, not_change=True)
return True return True
except Exception: except Exception:
return False return False
@ -1030,28 +1020,30 @@ class ChromiumShadowRootElement(BaseElement):
css_paths = [i.css_path[47:] for i in eles] css_paths = [i.css_path[47:] for i in eles]
if single: if single:
node_id = self.page.run_cdp('DOM.querySelector', nodeId=self._node_id, selector=css_paths[0])['nodeId'] node_id = self.page.run_cdp('DOM.querySelector',
return ChromiumElement(self.page, node_id) if node_id else None nodeId=self._node_id, selector=css_paths[0], not_change=True)['nodeId']
return _make_chromium_ele(self.page, node_id=node_id) if node_id else None
else: else:
results = [] results = []
for i in css_paths: for i in css_paths:
node_id = self.page.run_cdp('DOM.querySelector', nodeId=self._node_id, selector=i)['nodeId'] node_id = self.page.run_cdp('DOM.querySelector',
nodeId=self._node_id, selector=i, not_change=True)['nodeId']
if node_id: if node_id:
results.append(ChromiumElement(self.page, node_id)) results.append(_make_chromium_ele(self.page, node_id=node_id))
return results return results
def _get_node_id(self, obj_id): def _get_node_id(self, obj_id):
"""返回元素node id""" """返回元素node id"""
return self.page.run_cdp('DOM.requestNode', objectId=obj_id)['nodeId'] return self.page.run_cdp('DOM.requestNode', objectId=obj_id, not_change=True)['nodeId']
def _get_obj_id(self, back_id): def _get_obj_id(self, back_id):
"""返回元素object id""" """返回元素object id"""
return self.page.run_cdp('DOM.resolveNode', backendNodeId=back_id)['object']['objectId'] return self.page.run_cdp('DOM.resolveNode', backendNodeId=back_id, not_change=True)['object']['objectId']
def _get_backend_id(self, node_id): def _get_backend_id(self, node_id):
"""返回元素object id""" """返回元素object id"""
return self.page.run_cdp('DOM.describeNode', nodeId=node_id)['node']['backendNodeId'] return self.page.run_cdp('DOM.describeNode', nodeId=node_id, not_change=True)['node']['backendNodeId']
def make_chromium_ele(ele, loc, single=True, timeout=None, relative=True): def make_chromium_ele(ele, loc, single=True, timeout=None, relative=True):
@ -1179,14 +1171,9 @@ def _find_by_css(ele, selector, single, timeout):
def _make_chromium_ele(page, node_id=None, obj_id=None): def _make_chromium_ele(page, node_id=None, obj_id=None):
"""根据node id或object id生成相应元素对象""" """根据node id或object id生成相应元素对象"""
ele = ChromiumElement(page, obj_id=obj_id, node_id=node_id) ele = ChromiumElement(page, obj_id=obj_id, node_id=node_id)
if ele.tag in ('iframe', 'frame') and ele.attr('src'): if ele.tag in ('iframe', 'frame'):
src = ele.attr('src') from .chromium_frame import ChromiumFrame
if src: ele = ChromiumFrame(page, ele)
netloc1 = urlparse(src).netloc
netloc2 = urlparse(page.url).netloc
if netloc1 != netloc2:
# from .chromium_base import ChromiumFrame
ele = ChromiumFrame(page, ele)
return ele return ele
@ -1232,13 +1219,14 @@ else{a.push(e.snapshotItem(i));}}"""
return js return js
def run_script(page_or_ele, script, as_expr=False, timeout=None, args=None): def run_script(page_or_ele, script, as_expr=False, timeout=None, args=None, not_change=False):
"""运行javascript代码 \n """运行javascript代码 \n
:param page_or_ele: 页面对象或元素对象 :param page_or_ele: 页面对象或元素对象
:param script: js文本 :param script: js文本
:param as_expr: 是否作为表达式运行为True时args无效 :param as_expr: 是否作为表达式运行为True时args无效
:param timeout: 超时时间 :param timeout: 超时时间
:param args: 参数按顺序在js文本中对应argument[0]argument[2]... :param args: 参数按顺序在js文本中对应argument[0]argument[2]...
:param not_change: 执行时是否切换页面对象模式
:return: js执行结果 :return: js执行结果
""" """
if isinstance(page_or_ele, (ChromiumElement, ChromiumShadowRootElement)): if isinstance(page_or_ele, (ChromiumElement, ChromiumShadowRootElement)):
@ -1257,7 +1245,9 @@ def run_script(page_or_ele, script, as_expr=False, timeout=None, args=None):
returnByValue=False, returnByValue=False,
awaitPromise=True, awaitPromise=True,
userGesture=True, userGesture=True,
timeout=timeout * 1000) timeout=timeout * 1000,
not_change=not_change)
else: else:
args = args or () args = args or ()
if not is_js_func(script): if not is_js_func(script):
@ -1268,7 +1258,8 @@ def run_script(page_or_ele, script, as_expr=False, timeout=None, args=None):
arguments=[_convert_argument(arg) for arg in args], arguments=[_convert_argument(arg) for arg in args],
returnByValue=False, returnByValue=False,
awaitPromise=True, awaitPromise=True,
userGesture=True) userGesture=True,
not_change=not_change)
exceptionDetails = res.get('exceptionDetails') exceptionDetails = res.get('exceptionDetails')
if exceptionDetails: if exceptionDetails:

View File

@ -7,11 +7,12 @@
from pathlib import Path from pathlib import Path
from typing import Union, Tuple, List, Any from typing import Union, Tuple, List, Any
from .chromium_base import ChromiumBase
from .chromium_page import ChromiumPage
from .web_page import WebPage
from .base import DrissionElement, BaseElement from .base import DrissionElement, BaseElement
from .chromium_base import ChromiumBase
from .chromium_frame import ChromiumFrame
from .chromium_page import ChromiumPage
from .session_element import SessionElement from .session_element import SessionElement
from .web_page import WebPage
class ChromiumElement(DrissionElement): class ChromiumElement(DrissionElement):
@ -33,7 +34,7 @@ class ChromiumElement(DrissionElement):
def __call__(self, def __call__(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = ...) -> Union['ChromiumElement', str, None]: ... timeout: float = ...) -> Union[ChromiumElement, ChromiumFrame, str, None]: ...
@property @property
def tag(self) -> str: ... def tag(self) -> str: ...
@ -64,31 +65,31 @@ class ChromiumElement(DrissionElement):
def doc_id(self) -> str: ... def doc_id(self) -> str: ...
@property @property
def size(self) -> dict: ... def size(self) -> tuple: ...
@property @property
def client_location(self) -> Union[dict, None]: ... def client_location(self) -> tuple: ...
@property @property
def client_midpoint(self) -> Union[dict, None]: ... def client_midpoint(self) -> tuple: ...
@property @property
def location(self) -> Union[dict, None]: ... def location(self) -> tuple: ...
@property @property
def midpoint(self) -> dict: ... def midpoint(self) -> tuple: ...
@property @property
def _client_click_point(self) -> Union[dict, None]: ... def _client_click_point(self) -> tuple: ...
@property @property
def _click_point(self) -> Union[dict, None]: ... def _click_point(self) -> tuple: ...
@property @property
def shadow_root(self) -> Union[None, 'ChromiumShadowRootElement']: ... def shadow_root(self) -> Union[None, ChromiumShadowRootElement]: ...
@property @property
def sr(self): ... def sr(self) -> Union[None, ChromiumShadowRootElement]: ...
@property @property
def pseudo_before(self) -> str: ... def pseudo_before(self) -> str: ...
@ -97,44 +98,44 @@ class ChromiumElement(DrissionElement):
def pseudo_after(self) -> str: ... def pseudo_after(self) -> str: ...
@property @property
def scroll(self) -> 'ChromeScroll': ... def scroll(self) -> ChromeScroll: ...
def parent(self, level_or_loc: Union[tuple, str, int] = ...) -> Union['ChromiumElement', None]: ... def parent(self, level_or_loc: Union[tuple, str, int] = ...) -> Union[ChromiumElement, None]: ...
def prev(self, def prev(self,
filter_loc: Union[tuple, str] = ..., filter_loc: Union[tuple, str] = ...,
index: int = ..., index: int = ...,
timeout: float = ...) -> Union['ChromiumElement', str, None]: ... timeout: float = ...) -> Union[ChromiumElement, str, None]: ...
def next(self, def next(self,
filter_loc: Union[tuple, str] = ..., filter_loc: Union[tuple, str] = ...,
index: int = ..., index: int = ...,
timeout: float = ...) -> Union['ChromiumElement', str, None]: ... timeout: float = ...) -> Union[ChromiumElement, str, None]: ...
def before(self, def before(self,
filter_loc: Union[tuple, str] = ..., filter_loc: Union[tuple, str] = ...,
index: int = ..., index: int = ...,
timeout: float = ...) -> Union['ChromiumElement', str, None]: ... timeout: float = ...) -> Union[ChromiumElement, str, None]: ...
def after(self, def after(self,
filter_loc: Union[tuple, str] = ..., filter_loc: Union[tuple, str] = ...,
index: int = ..., index: int = ...,
timeout: float = ...) -> Union['ChromiumElement', str, None]: ... timeout: float = ...) -> Union[ChromiumElement, str, None]: ...
def prevs(self, def prevs(self,
filter_loc: Union[tuple, str] = ..., filter_loc: Union[tuple, str] = ...,
timeout: float = ...) -> List[Union['ChromiumElement', str]]: ... timeout: float = ...) -> List[Union[ChromiumElement, str]]: ...
def nexts(self, def nexts(self,
filter_loc: Union[tuple, str] = ..., filter_loc: Union[tuple, str] = ...,
timeout: float = ...) -> List[Union['ChromiumElement', str]]: ... timeout: float = ...) -> List[Union[ChromiumElement, str]]: ...
def befores(self, def befores(self,
filter_loc: Union[tuple, str] = ..., filter_loc: Union[tuple, str] = ...,
timeout: float = ...) -> List[Union['ChromiumElement', str]]: ... timeout: float = ...) -> List[Union[ChromiumElement, str]]: ...
def wait_ele(self, def wait_ele(self,
loc_or_ele: Union[str, tuple, 'ChromiumElement'], loc_or_ele: Union[str, tuple, ChromiumElement],
timeout: float = ...) -> 'ChromiumElementWaiter': ... timeout: float = ...) -> 'ChromiumElementWaiter': ...
@property @property
@ -173,11 +174,11 @@ class ChromiumElement(DrissionElement):
def ele(self, def ele(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = ...) -> Union['ChromiumElement', str, None]: ... timeout: float = ...) -> Union[ChromiumElement, ChromiumFrame, str, None]: ...
def eles(self, def eles(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = ...) -> List[Union['ChromiumElement', str]]: ... timeout: float = ...) -> List[Union[ChromiumElement, ChromiumFrame, str]]: ...
def s_ele(self, loc_or_str: Union[Tuple[str, str], str] = ...) -> Union[SessionElement, str, None]: ... def s_ele(self, loc_or_str: Union[Tuple[str, str], str] = ...) -> Union[SessionElement, str, None]: ...
@ -186,7 +187,7 @@ class ChromiumElement(DrissionElement):
def _ele(self, def _ele(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = ..., single: bool = ..., relative: bool = ...) \ timeout: float = ..., single: bool = ..., relative: bool = ...) \
-> Union['ChromiumElement', str, None, List[Union['ChromiumElement', str]]]: ... -> Union[ChromiumElement, ChromiumFrame, str, None, List[Union[ChromiumElement, ChromiumFrame, str]]]: ...
def style(self, style: str, pseudo_ele: str = ...) -> str: ... def style(self, style: str, pseudo_ele: str = ...) -> str: ...
@ -217,7 +218,7 @@ class ChromiumElement(DrissionElement):
def drag(self, offset_x: int = ..., offset_y: int = ..., speed: int = ..., shake: bool = ...) -> None: ... def drag(self, offset_x: int = ..., offset_y: int = ..., speed: int = ..., shake: bool = ...) -> None: ...
def drag_to(self, def drag_to(self,
ele_or_loc: Union[tuple, 'ChromiumElement'], ele_or_loc: Union[tuple, ChromiumElement],
speed: int = ..., speed: int = ...,
shake: bool = ...) -> None: ... shake: bool = ...) -> None: ...
@ -248,7 +249,7 @@ class ChromiumShadowRootElement(BaseElement):
def __call__(self, def __call__(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = ...) -> Union[ChromiumElement, None]: ... timeout: float = ...) -> Union[ChromiumElement, ChromiumFrame, None]: ...
@property @property
def is_enabled(self) -> bool: ... def is_enabled(self) -> bool: ...
@ -297,20 +298,21 @@ class ChromiumShadowRootElement(BaseElement):
def ele(self, def ele(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = ...) -> Union[ChromiumElement, None]: ... timeout: float = ...) -> Union[ChromiumElement, ChromiumFrame, None]: ...
def eles(self, def eles(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = ...) -> List[ChromiumElement]: ... timeout: float = ...) -> List[Union[ChromiumElement, ChromiumFrame]]: ...
def s_ele(self, loc_or_str: Union[Tuple[str, str], str] = ...) -> Union[SessionElement, str, None]: ... def s_ele(self, loc_or_str: Union[Tuple[str, str], str] = ...) -> Union[SessionElement, str, None]: ...
def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[SessionElement]: ... def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[Union[SessionElement, str]]: ...
def _ele(self, def _ele(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = ..., timeout: float = ...,
single: bool = ..., relative: bool = ...) -> Union['ChromiumElement', None, List[ChromiumElement]]: ... single: bool = ..., relative: bool = ...) \
-> Union[ChromiumElement, ChromiumFrame, None, str, List[Union[ChromiumElement, ChromiumFrame, str]]]: ...
def _get_node_id(self, obj_id: str) -> str: ... def _get_node_id(self, obj_id: str) -> str: ...
@ -346,8 +348,7 @@ def _make_js_for_find_ele_by_xpath(xpath: str, type_txt: str, node_txt: str) ->
def run_script(page_or_ele: Union[ChromiumBase, ChromiumElement, ChromiumShadowRootElement], script: str, def run_script(page_or_ele: Union[ChromiumBase, ChromiumElement, ChromiumShadowRootElement], script: str,
as_expr: bool = ..., as_expr: bool = ..., timeout: float = ..., args: tuple = ..., not_change:bool=...) -> Any: ...
timeout: float = ..., args: tuple = ...) -> Any: ...
def _parse_js_result(page: ChromiumBase, ele: ChromiumElement, result: dict): ... def _parse_js_result(page: ChromiumBase, ele: ChromiumElement, result: dict): ...

View File

@ -149,9 +149,9 @@ class ChromiumPage(ChromiumBase):
raise TypeError(f'不支持的文件格式:{pic_type}') raise TypeError(f'不支持的文件格式:{pic_type}')
pic_type = 'jpeg' if pic_type == '.jpg' else pic_type[1:] pic_type = 'jpeg' if pic_type == '.jpg' else pic_type[1:]
hw = self.size width, height = self.size
if full_page: if full_page:
vp = {'x': 0, 'y': 0, 'width': hw['width'], 'height': hw['height'], 'scale': 1} vp = {'x': 0, 'y': 0, 'width': width, 'height': height, 'scale': 1}
png = self._wait_driver.Page.captureScreenshot(format=pic_type, captureBeyondViewport=True, clip=vp)['data'] png = self._wait_driver.Page.captureScreenshot(format=pic_type, captureBeyondViewport=True, clip=vp)['data']
else: else:
if left_top and right_bottom: if left_top and right_bottom:

View File

@ -264,7 +264,8 @@ def make_session_ele(html_or_ele, loc=None, single=True):
raise ValueError("定位符必须为str或长度为2的tuple。") raise ValueError("定位符必须为str或长度为2的tuple。")
# ---------------根据传入对象类型获取页面对象和lxml元素对象--------------- # ---------------根据传入对象类型获取页面对象和lxml元素对象---------------
if isinstance(html_or_ele, SessionElement): # SessionElement the_type = str(type(html_or_ele))
if the_type.endswith(".SessionElement'>"): # SessionElement
page = html_or_ele.page page = html_or_ele.page
loc_str = loc[1] loc_str = loc[1]
@ -285,7 +286,7 @@ def make_session_ele(html_or_ele, loc=None, single=True):
loc = loc[0], loc_str loc = loc[0], loc_str
elif isinstance(html_or_ele, DrissionElement): # ChromiumElement, DriverElement elif the_type.endswith((".ChromiumElement'>", ".DriverElement'>")): # ChromiumElement, DriverElement
loc_str = loc[1] loc_str = loc[1]
if loc[0] == 'xpath' and loc[1].lstrip().startswith('/'): if loc[0] == 'xpath' and loc[1].lstrip().startswith('/'):
loc_str = f'.{loc[1]}' loc_str = f'.{loc[1]}'
@ -296,14 +297,14 @@ def make_session_ele(html_or_ele, loc=None, single=True):
# 获取整个页面html再定位到当前元素以实现查找上级元素 # 获取整个页面html再定位到当前元素以实现查找上级元素
page = html_or_ele.page page = html_or_ele.page
xpath = html_or_ele.xpath xpath = html_or_ele.xpath
if hasattr(html_or_ele, 'doc_id'): # ChromiumElement支持元素在iframe内的情况 if hasattr(html_or_ele, 'doc_id'): # ChromiumElement兼容传入的元素在iframe内的情况
html = html_or_ele.page.run_cdp('DOM.getOuterHTML', objectId=html_or_ele.doc_id)['outerHTML'] html = html_or_ele.page.run_cdp('DOM.getOuterHTML', objectId=html_or_ele.doc_id)['outerHTML']
else: else:
html = html_or_ele.page.html html = html_or_ele.page.html
html_or_ele = fromstring(html) html_or_ele = fromstring(html)
html_or_ele = html_or_ele.xpath(xpath)[0] html_or_ele = html_or_ele.xpath(xpath)[0]
elif isinstance(html_or_ele, BasePage): # MixPage, DriverPage 或 SessionPage elif isinstance(html_or_ele, BasePage): # 各种页面对象
page = html_or_ele page = html_or_ele
html_or_ele = fromstring(html_or_ele.html) html_or_ele = fromstring(html_or_ele.html)
@ -311,7 +312,8 @@ def make_session_ele(html_or_ele, loc=None, single=True):
page = None page = None
html_or_ele = fromstring(html_or_ele) html_or_ele = fromstring(html_or_ele)
elif isinstance(html_or_ele, BaseElement): # ShadowRootElement # ShadowRootElement, ChromiumShadowRootElement, ChromiumFrame
elif isinstance(html_or_ele, BaseElement) or the_type.endswith(".ChromiumFrame'>"):
page = html_or_ele.page page = html_or_ele.page
html_or_ele = fromstring(html_or_ele.html) html_or_ele = fromstring(html_or_ele.html)

View File

@ -3,7 +3,10 @@ from typing import Union, List, Tuple
from lxml.html import HtmlElement from lxml.html import HtmlElement
from .base import DrissionElement, BasePage, BaseElement from .base import DrissionElement, BaseElement
from .chromium_base import ChromiumFrame, ChromiumBase
from .chromium_element import ChromiumElement
from .driver_element import DriverElement
from .session_page import SessionPage from .session_page import SessionPage
@ -104,6 +107,7 @@ class SessionElement(DrissionElement):
def _get_ele_path(self, mode: str) -> str: ... def _get_ele_path(self, mode: str) -> str: ...
def make_session_ele(html_or_ele: Union[str, BaseElement, BasePage], def make_session_ele(html_or_ele: Union[str, SessionElement, ChromiumElement, DriverElement, BaseElement, ChromiumFrame,
ChromiumBase],
loc: Union[str, Tuple[str, str]] = ..., loc: Union[str, Tuple[str, str]] = ...,
single: bool = ...) -> Union[SessionElement, str, None, List[Union[SessionElement, str]]]: ... single: bool = ...) -> Union[SessionElement, str, None, List[Union[SessionElement, str]]]: ...

View File

@ -5,8 +5,8 @@ from DownloadKit import DownloadKit
from requests import Session, Response from requests import Session, Response
from .base import BasePage from .base import BasePage
from .chromium_base import ChromiumFrame
from .chromium_element import ChromiumElement from .chromium_element import ChromiumElement
from .chromium_frame import ChromiumFrame
from .chromium_page import ChromiumPage from .chromium_page import ChromiumPage
from .config import DriverOptions, SessionOptions from .config import DriverOptions, SessionOptions
from .session_element import SessionElement from .session_element import SessionElement
@ -99,7 +99,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = ...) -> List[Union[ChromiumElement, SessionElement, ChromiumFrame, str]]: ... timeout: float = ...) -> List[Union[ChromiumElement, SessionElement, ChromiumFrame, str]]: ...
def s_ele(self, loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, SessionElement] = ...) \ def s_ele(self, loc_or_ele: Union[Tuple[str, str], str] = ...) \
-> Union[SessionElement, str, None]: ... -> Union[SessionElement, str, None]: ...
def s_eles(self, loc_or_str: Union[Tuple[str, str], str] = ...) -> List[Union[SessionElement, str]]: ... def s_eles(self, loc_or_str: Union[Tuple[str, str], str] = ...) -> List[Union[SessionElement, str]]: ...
@ -147,7 +147,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
def download(self) -> DownloadKit: ... def download(self) -> DownloadKit: ...
def _ele(self, def _ele(self,
loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, SessionElement], loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, SessionElement, ChromiumFrame],
timeout: float = ..., single: bool = ..., relative: bool = ...) \ timeout: float = ..., single: bool = ..., relative: bool = ...) \
-> Union[ChromiumElement, SessionElement, ChromiumFrame, str, None, List[Union[SessionElement, str]], List[ -> Union[ChromiumElement, SessionElement, ChromiumFrame, str, None, List[Union[SessionElement, str]], List[
Union[ChromiumElement, str, ChromiumFrame]]]: ... Union[ChromiumElement, str, ChromiumFrame]]]: ...