4.1.0.0b7元素对象也加上get_frame();move_to()的偏移量参数默认为None;修复auto_port()问题

This commit is contained in:
g1879 2024-07-15 16:59:16 +08:00
parent 329e49ea7c
commit d0d3fea3be
9 changed files with 79 additions and 48 deletions

View File

@ -14,4 +14,4 @@ from ._pages.chromium_page import ChromiumPage
from ._pages.mix_page import MixPage
from ._pages.mix_page import MixPage as WebPage
__version__ = '4.1.0.0b4'
__version__ = '4.1.0.0b7'

View File

@ -13,6 +13,7 @@ from urllib.parse import quote
from DownloadKit import DownloadKit
from .._elements.none_element import NoneElement
from .._functions.elements import get_frame
from .._functions.locator import get_loc
from .._functions.settings import Settings
from .._functions.web import format_html
@ -70,6 +71,16 @@ class BaseElement(BaseParser):
def nexts(self):
pass
def get_frame(self, loc_or_ind, timeout=None):
"""获取元素中一个frame对象
:param loc_or_ind: 定位符iframe序号序号从1开始可传入负数获取倒数第几个
:param timeout: 查找元素超时时间
:return: ChromiumFrame对象
"""
if not isinstance(loc_or_ind, (int, str, tuple)):
raise TypeError('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):
"""调用获取元素的方法
:param locator: 定位符

View File

@ -823,7 +823,7 @@ class ChromiumElement(DrissionElement):
self._run_js('this.focus();')
def hover(self, offset_x=None, offset_y=None):
"""鼠标悬停,可接受偏移量,偏移量相对于元素左上角坐标。不传入x或y值时悬停在元素中点
"""鼠标悬停,可接受偏移量,偏移量相对于元素左上角坐标。不传入offset_x和offset_y值时悬停在元素中点
:param offset_x: 相对元素左上角坐标的x轴偏移量
:param offset_y: 相对元素左上角坐标的y轴偏移量
:return: None

View File

@ -7,6 +7,7 @@
"""
from time import perf_counter
from .locator import is_loc
from .._elements.none_element import NoneElement
@ -402,6 +403,50 @@ def get_eles(locators, owner, any_one=False, first_ele=True, timeout=10):
return res
def get_frame(owner, loc_ind_ele, timeout=None):
"""获取页面中一个frame对象
:param owner: 要在其中查找元素的对象
:param loc_ind_ele: 定位符iframe序号ChromiumFrame对象序号从1开始可传入负数获取倒数第几个
:param timeout: 查找元素超时时间
:return: ChromiumFrame对象
"""
if isinstance(loc_ind_ele, str):
if not is_loc(loc_ind_ele):
xpath = f'xpath://*[(name()="iframe" or name()="frame") and ' \
f'(@name="{loc_ind_ele}" or @id="{loc_ind_ele}")]'
else:
xpath = loc_ind_ele
ele = owner._ele(xpath, timeout=timeout)
if ele and ele._type != 'ChromiumFrame':
raise TypeError('该定位符不是指向frame元素。')
r = ele
elif isinstance(loc_ind_ele, tuple):
ele = owner._ele(loc_ind_ele, timeout=timeout)
if ele and ele._type != 'ChromiumFrame':
raise TypeError('该定位符不是指向frame元素。')
r = ele
elif isinstance(loc_ind_ele, int):
if loc_ind_ele == 0:
loc_ind_ele = 1
elif loc_ind_ele < 0:
loc_ind_ele = f'last()+{loc_ind_ele}+1'
xpath = f'xpath:(//*[name()="frame" or name()="iframe"])[{loc_ind_ele}]'
r = owner._ele(xpath, timeout=timeout)
elif loc_ind_ele._type == 'ChromiumFrame':
r = loc_ind_ele
else:
raise TypeError('必须传入定位符、iframe序号、id、name、ChromiumFrame对象其中之一。')
if isinstance(r, NoneElement):
r.method = 'get_frame()'
r.args = {'loc_ind_ele': loc_ind_ele}
return r
def _get_attr_all(src_list, aim_list, name, value, method, equal=True):
if equal:
for i in src_list:

View File

@ -10,6 +10,7 @@ from typing import Union, List, Optional, Iterable
from .._base.base import BaseParser
from .._elements.chromium_element import ChromiumElement
from .._elements.session_element import SessionElement
from .._pages.chromium_frame import ChromiumFrame
def get_eles(locators: Union[List[str], tuple],
@ -19,6 +20,11 @@ def get_eles(locators: Union[List[str], tuple],
timeout: float = 10) -> dict: ...
def get_frame(owner: BaseParser,
loc_ind_ele: Union[str, int, tuple, ChromiumFrame, ChromiumElement],
timeout: float = None) -> ChromiumFrame: ...
class SessionElementsList(list):
_page = ...

View File

@ -19,7 +19,7 @@ from ..errors import (ContextLostError, ElementLostError, CDPError, PageDisconne
class PortFinder(object):
used_port = set()
prev_time = None
prev_time = 0
lock = Lock()
checked_paths = set()
@ -43,9 +43,8 @@ class PortFinder(object):
"""
from random import randint
with PortFinder.lock:
if PortFinder.prev_time and perf_counter() - PortFinder.prev_time > 30:
if PortFinder.prev_time and perf_counter() - PortFinder.prev_time > 60:
PortFinder.used_port.clear()
PortFinder.prev_time = perf_counter()
if scope in (True, None):
scope = (9600, 59600)
max_times = scope[1] - scope[0]
@ -61,6 +60,8 @@ class PortFinder(object):
rmtree(path)
except:
continue
PortFinder.used_port.add(port)
PortFinder.prev_time = perf_counter()
return port, str(path)
raise OSError('未找到可用端口。')

View File

@ -19,8 +19,8 @@ from .._elements.chromium_element import run_js, make_chromium_eles
from .._elements.none_element import NoneElement
from .._elements.session_element import make_session_ele
from .._functions.cookies import CookiesList
from .._functions.elements import SessionElementsList
from .._functions.locator import get_loc, is_loc
from .._functions.elements import SessionElementsList, get_frame
from .._functions.locator import get_loc
from .._functions.settings import Settings
from .._functions.tools import raise_error
from .._functions.web import location_in_viewport
@ -770,41 +770,7 @@ class ChromiumBase(BasePage):
:param timeout: 查找元素超时时间
:return: ChromiumFrame对象
"""
if isinstance(loc_ind_ele, str):
if not is_loc(loc_ind_ele):
xpath = f'xpath://*[(name()="iframe" or name()="frame") and ' \
f'(@name="{loc_ind_ele}" or @id="{loc_ind_ele}")]'
else:
xpath = loc_ind_ele
ele = self._ele(xpath, timeout=timeout)
if ele and ele._type != 'ChromiumFrame':
raise TypeError('该定位符不是指向frame元素。')
r = ele
elif isinstance(loc_ind_ele, tuple):
ele = self._ele(loc_ind_ele, timeout=timeout)
if ele and ele._type != 'ChromiumFrame':
raise TypeError('该定位符不是指向frame元素。')
r = ele
elif isinstance(loc_ind_ele, int):
if loc_ind_ele == 0:
loc_ind_ele = 1
elif loc_ind_ele < 0:
loc_ind_ele = f'last()+{loc_ind_ele}+1'
xpath = f'xpath:(//*[name()="frame" or name()="iframe"])[{loc_ind_ele}]'
r = self._ele(xpath, timeout=timeout)
elif loc_ind_ele._type == 'ChromiumFrame':
r = loc_ind_ele
else:
raise TypeError('必须传入定位符、iframe序号、id、name、ChromiumFrame对象其中之一。')
if isinstance(r, NoneElement):
r.method = 'get_frame()'
r.args = {'loc_ind_ele': loc_ind_ele}
return r
return get_frame(self, loc_ind_ele=loc_ind_ele, timeout=timeout)
def get_frames(self, locator=None, timeout=None):
"""获取所有符合条件的frame对象

View File

@ -25,7 +25,7 @@ class Actions:
self.curr_y = 0
self._holding = 'left'
def move_to(self, ele_or_loc, offset_x=0, offset_y=0, duration=.5):
def move_to(self, ele_or_loc, offset_x=None, offset_y=None, duration=.5):
"""鼠标移动到元素中点,或页面上的某个绝对坐标。可设置偏移量
当带偏移量时偏移量相对于元素左上角坐标
:param ele_or_loc: 元素对象绝对坐标或文本定位符坐标为tuple(int, int)形式
@ -35,6 +35,11 @@ class Actions:
:return: self
"""
is_loc = False
mid_point = offset_x == offset_y is None
if offset_x is None:
offset_x = 0
if offset_y is None:
offset_y = 0
if isinstance(ele_or_loc, (tuple, list)):
is_loc = True
lx = ele_or_loc[0] + offset_x
@ -42,7 +47,7 @@ class Actions:
elif isinstance(ele_or_loc, str) or ele_or_loc._type == 'ChromiumElement':
ele_or_loc = self.owner(ele_or_loc)
self.owner.scroll.to_see(ele_or_loc)
x, y = ele_or_loc.rect.location if offset_x or offset_y else ele_or_loc.rect.midpoint
x, y = ele_or_loc.rect.midpoint if mid_point else ele_or_loc.rect.location
lx = x + offset_x
ly = y + offset_y
else:
@ -58,8 +63,7 @@ class Actions:
if is_loc:
cx, cy = location_to_client(self.owner, lx, ly)
else:
x, y = ele_or_loc.rect.viewport_location if offset_x or offset_y \
else ele_or_loc.rect.viewport_midpoint
x, y = ele_or_loc.rect.viewport_midpoint if mid_point else ele_or_loc.rect.viewport_location
cx = x + offset_x
cy = y + offset_y

View File

@ -42,8 +42,6 @@ class BrowserWaiter(OriginWaiter):
class BaseWaiter(OriginWaiter):
_owner: ChromiumBase = ...
def __call__(self, second: float, scope: float = None) -> ChromiumBase: ...
def ele_deleted(self,
loc_or_ele: Union[str, tuple, ChromiumElement],
timeout: float = None,