mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
修复frame内元素无法使用s_ele()问题;更新文档
This commit is contained in:
parent
d68763c398
commit
925a7400c7
@ -6,7 +6,7 @@
|
||||
"""
|
||||
from abc import abstractmethod
|
||||
from re import sub
|
||||
from typing import Union, Tuple, List
|
||||
from typing import Union, List
|
||||
from urllib.parse import quote
|
||||
|
||||
from .common import format_html, get_loc
|
||||
@ -26,7 +26,7 @@ class BaseParser(object):
|
||||
|
||||
# ----------------以下属性或方法待后代实现----------------
|
||||
@property
|
||||
def html(self) -> str:
|
||||
def html(self):
|
||||
return ''
|
||||
|
||||
def s_ele(self, loc_or_ele):
|
||||
@ -59,16 +59,16 @@ class BaseElement(BaseParser):
|
||||
def _ele(self, loc_or_str, timeout=None, single=True, relative=False):
|
||||
pass
|
||||
|
||||
def parent(self, level_or_loc = 1):
|
||||
def parent(self, level_or_loc=1):
|
||||
pass
|
||||
|
||||
def prev(self, index = 1) -> None:
|
||||
def prev(self, index=1) -> None:
|
||||
return None # ShadowRootElement直接继承
|
||||
|
||||
def prevs(self) -> None:
|
||||
return None # ShadowRootElement直接继承
|
||||
|
||||
def next(self, index = 1):
|
||||
def next(self, index=1):
|
||||
pass
|
||||
|
||||
def nexts(self):
|
||||
@ -290,7 +290,7 @@ class DrissionElement(BaseElement):
|
||||
class BasePage(BaseParser):
|
||||
"""页面类的基类"""
|
||||
|
||||
def __init__(self, timeout = 10):
|
||||
def __init__(self, timeout=10):
|
||||
"""初始化函数"""
|
||||
self._url = None
|
||||
self.timeout = timeout
|
||||
@ -346,9 +346,9 @@ class BasePage(BaseParser):
|
||||
return
|
||||
|
||||
@abstractmethod
|
||||
def get_cookies(self, as_dict= False):
|
||||
def get_cookies(self, as_dict=False):
|
||||
return {}
|
||||
|
||||
@abstractmethod
|
||||
def get(self, url, show_errmsg= False, retry = None, interval= None):
|
||||
def get(self, url, show_errmsg=False, retry=None, interval=None):
|
||||
pass
|
||||
|
@ -259,7 +259,7 @@ class ChromiumBase(BasePage):
|
||||
@property
|
||||
def set_page_load_strategy(self):
|
||||
"""返回用于设置页面加载策略的对象"""
|
||||
return pageLoadStrategy(self)
|
||||
return PageLoadStrategy(self)
|
||||
|
||||
def set_timeouts(self, implicit=None, page_load=None, script=None):
|
||||
"""设置超时时间,单位为秒 \n
|
||||
@ -367,13 +367,13 @@ class ChromiumBase(BasePage):
|
||||
"""
|
||||
return self._ele(loc_or_ele, timeout=timeout)
|
||||
|
||||
def eles(self, loc_or_ele, timeout=None):
|
||||
def eles(self, loc_or_str, timeout=None):
|
||||
"""获取所有符合条件的元素对象 \n
|
||||
:param loc_or_ele: 定位符或元素对象
|
||||
:param loc_or_str: 定位符或元素对象
|
||||
:param timeout: 查找超时时间
|
||||
:return: ChromiumElement对象组成的列表
|
||||
"""
|
||||
return self._ele(loc_or_ele, timeout=timeout, single=False)
|
||||
return self._ele(loc_or_str, timeout=timeout, single=False)
|
||||
|
||||
def s_ele(self, loc_or_ele=None):
|
||||
"""查找第一个符合条件的元素以SessionElement形式返回,处理复杂页面时效率很高 \n
|
||||
@ -808,7 +808,7 @@ class Timeout(object):
|
||||
return self.page.timeout
|
||||
|
||||
|
||||
class pageLoadStrategy(object):
|
||||
class PageLoadStrategy(object):
|
||||
"""用于设置页面加载策略的类"""
|
||||
|
||||
def __init__(self, page):
|
||||
@ -826,14 +826,14 @@ class pageLoadStrategy(object):
|
||||
raise ValueError("只能选择 'normal', 'eager', 'none'。")
|
||||
self.page._page_load_strategy = value
|
||||
|
||||
def set_normal(self):
|
||||
def normal(self):
|
||||
"""设置页面加载策略为normal"""
|
||||
self.page._page_load_strategy = 'normal'
|
||||
|
||||
def set_eager(self):
|
||||
def eager(self):
|
||||
"""设置页面加载策略为eager"""
|
||||
self.page._page_load_strategy = 'eager'
|
||||
|
||||
def set_none(self):
|
||||
def none(self):
|
||||
"""设置页面加载策略为none"""
|
||||
self.page._page_load_strategy = 'none'
|
||||
|
@ -134,7 +134,7 @@ class ChromiumBase(BasePage):
|
||||
timeout: float = ...) -> Union[ChromiumElement, 'ChromiumFrame', None]: ...
|
||||
|
||||
def eles(self,
|
||||
loc_or_ele: Union[Tuple[str, str], str],
|
||||
loc_or_str: Union[Tuple[str, str], str],
|
||||
timeout: float = ...) -> List[Union[ChromiumElement, 'ChromiumFrame']]: ...
|
||||
|
||||
def s_ele(self, loc_or_ele: Union[Tuple[str, str], str, ChromiumElement] = ...) \
|
||||
@ -282,14 +282,14 @@ class Timeout(object):
|
||||
def implicit(self) -> float: ...
|
||||
|
||||
|
||||
class pageLoadStrategy(object):
|
||||
class PageLoadStrategy(object):
|
||||
def __init__(self, page: ChromiumBase):
|
||||
self.page: ChromiumBase = ...
|
||||
|
||||
def __call__(self, value: str) -> None: ...
|
||||
|
||||
def set_normal(self) -> None: ...
|
||||
def normal(self) -> None: ...
|
||||
|
||||
def set_eager(self) -> None: ...
|
||||
def eager(self) -> None: ...
|
||||
|
||||
def set_none(self) -> None: ...
|
||||
def none(self) -> None: ...
|
||||
|
@ -40,6 +40,8 @@ class ChromiumElement(DrissionElement):
|
||||
self._node_id = self._get_node_id(obj_id)
|
||||
self._obj_id = obj_id
|
||||
|
||||
self._doc_id = self.run_script('return this.ownerDocument;')['objectId']
|
||||
|
||||
def __repr__(self):
|
||||
attrs = self.attrs
|
||||
attrs = [f"{attr}='{attrs[attr]}'" for attr in attrs]
|
||||
@ -108,6 +110,11 @@ class ChromiumElement(DrissionElement):
|
||||
"""返回cdp中的node id"""
|
||||
return self._node_id
|
||||
|
||||
@property
|
||||
def doc_id(self):
|
||||
"""返回document的object id"""
|
||||
return self._doc_id
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
"""返回元素宽和高"""
|
||||
@ -1046,251 +1053,6 @@ class ChromiumShadowRootElement(BaseElement):
|
||||
return self.page.run_cdp('DOM.describeNode', nodeId=node_id)['node']['backendNodeId']
|
||||
|
||||
|
||||
# class ChromiumFrame(object):
|
||||
# def __init__(self, page, ele: ChromiumElement):
|
||||
# from .chromium_base import ChromiumBase
|
||||
# self.page: ChromiumBase = page
|
||||
# self._inner_ele = ele
|
||||
# self._is_diff_domain = False
|
||||
# self.frame_id = page.run_cdp('DOM.describeNode', nodeId=ele.node_id)['node'].get('frameId', None)
|
||||
#
|
||||
# src = ele.attr('src')
|
||||
# if src:
|
||||
# netloc1 = urlparse(src).netloc
|
||||
# netloc2 = urlparse(page.url).netloc
|
||||
# if netloc1 != netloc2:
|
||||
# self._is_diff_domain = True
|
||||
# from .chromium_base import ChromiumBase
|
||||
# self.inner_page = ChromiumBase(page.address, self.frame_id, page.timeout)
|
||||
# self.inner_page.set_page_load_strategy(self.page.page_load_strategy)
|
||||
# self.inner_page.timeouts = self.page.timeouts
|
||||
#
|
||||
# def __repr__(self) -> str:
|
||||
# attrs = self._inner_ele.attrs
|
||||
# attrs = [f"{attr}='{attrs[attr]}'" for attr in attrs]
|
||||
# return f'<ChromiumFrame {self._inner_ele.tag} {" ".join(attrs)}>'
|
||||
#
|
||||
# @property
|
||||
# def tag(self) -> str:
|
||||
# """返回元素tag"""
|
||||
# return self._inner_ele.tag
|
||||
#
|
||||
# @property
|
||||
# def url(self) -> str:
|
||||
# """"""
|
||||
# if self._is_diff_domain:
|
||||
# return self.inner_page.url
|
||||
# else:
|
||||
# r = self.page.run_cdp('DOM.describeNode', nodeId=self._inner_ele.node_id)
|
||||
# return r['node']['contentDocument']['documentURL']
|
||||
#
|
||||
# @property
|
||||
# def html(self) -> str:
|
||||
# """返回元素outerHTML文本"""
|
||||
# if self._is_diff_domain:
|
||||
# tag = self.tag
|
||||
# out_html = self.page.run_cdp('DOM.getOuterHTML', nodeId=self._inner_ele.node_id)['outerHTML']
|
||||
# in_html = self.inner_page.html
|
||||
# sign = search(rf'<{tag}.*?>', out_html).group(0)
|
||||
# return f'{sign}{in_html}</{tag}>'
|
||||
#
|
||||
# else:
|
||||
# return self._inner_ele.html
|
||||
#
|
||||
# @property
|
||||
# def title(self) -> str:
|
||||
# d = self.inner_page if self._is_diff_domain else self._inner_ele
|
||||
# ele = d.ele('xpath://title')
|
||||
# return ele.text if ele else None
|
||||
#
|
||||
# @property
|
||||
# def cookies(self):
|
||||
# return self.inner_page.cookies if self._is_diff_domain else self.page.cookies
|
||||
#
|
||||
# @property
|
||||
# def inner_html(self) -> str:
|
||||
# """返回元素innerHTML文本"""
|
||||
# return self.inner_page.html if self._is_diff_domain else self._inner_ele.inner_html
|
||||
#
|
||||
# @property
|
||||
# def attrs(self) -> dict:
|
||||
# return self._inner_ele.attrs
|
||||
#
|
||||
# @property
|
||||
# def frame_size(self) -> dict:
|
||||
# if self._is_diff_domain:
|
||||
# return self.inner_page.size
|
||||
# else:
|
||||
# h = self._inner_ele.run_script('return this.contentDocument.body.scrollHeight;')
|
||||
# w = self._inner_ele.run_script('return this.contentDocument.body.scrollWidth;')
|
||||
# return {'height': h, 'width': w}
|
||||
#
|
||||
# @property
|
||||
# def size(self) -> dict:
|
||||
# """返回frame元素大小"""
|
||||
# return self._inner_ele.size
|
||||
#
|
||||
# @property
|
||||
# def obj_id(self) -> str:
|
||||
# """返回js中的object id"""
|
||||
# return self._inner_ele.obj_id
|
||||
#
|
||||
# @property
|
||||
# def node_id(self) -> str:
|
||||
# """返回cdp中的node id"""
|
||||
# return self._inner_ele.node_id
|
||||
#
|
||||
# @property
|
||||
# def location(self) -> dict:
|
||||
# """返回frame元素左上角的绝对坐标"""
|
||||
# return self._inner_ele.location
|
||||
#
|
||||
# @property
|
||||
# def is_displayed(self) -> bool:
|
||||
# """返回frame元素是否显示"""
|
||||
# return self._inner_ele.is_displayed
|
||||
#
|
||||
# def get(self, url):
|
||||
# self.page._get(url, False, None, None, None, self.frame_id)
|
||||
#
|
||||
# def ele(self,
|
||||
# loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, 'ChromiumFrame'],
|
||||
# timeout: float = None):
|
||||
# d = self.inner_page if self._is_diff_domain else self._inner_ele
|
||||
# return d.ele(loc_or_ele, timeout)
|
||||
#
|
||||
# def eles(self,
|
||||
# loc_or_ele: Union[Tuple[str, str], str],
|
||||
# timeout: float = None):
|
||||
# d = self.inner_page if self._is_diff_domain else self._inner_ele
|
||||
# return d.eles(loc_or_ele, timeout)
|
||||
#
|
||||
# # def s_ele(self, loc_or_ele: Union[Tuple[str, str], str, ChromiumElement] = None) \
|
||||
# # -> Union[SessionElement, str, None]:
|
||||
# # """查找第一个符合条件的元素以SessionElement形式返回,处理复杂页面时效率很高 \n
|
||||
# # :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
# # :return: SessionElement对象或属性、文本
|
||||
# # """
|
||||
# # if isinstance(loc_or_ele, ChromiumElement):
|
||||
# # return make_session_ele(loc_or_ele)
|
||||
# # else:
|
||||
# # return make_session_ele(self, loc_or_ele)
|
||||
# #
|
||||
# # def s_eles(self, loc_or_str: Union[Tuple[str, str], str] = None) -> List[Union[SessionElement, str]]:
|
||||
# # """查找所有符合条件的元素以SessionElement列表形式返回 \n
|
||||
# # :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
# # :return: SessionElement对象组成的列表
|
||||
# # """
|
||||
# # return make_session_ele(self, loc_or_str, single=False)
|
||||
#
|
||||
# def attr(self, attr: str) -> Union[str, None]:
|
||||
# """返回frame元素attribute属性值 \n
|
||||
# :param attr: 属性名
|
||||
# :return: 属性值文本,没有该属性返回None
|
||||
# """
|
||||
# return self._inner_ele.attr(attr)
|
||||
#
|
||||
# def set_attr(self, attr: str, value: str) -> None:
|
||||
# """设置frame元素attribute属性 \n
|
||||
# :param attr: 属性名
|
||||
# :param value: 属性值
|
||||
# :return: None
|
||||
# """
|
||||
# self._inner_ele.set_attr(attr, value)
|
||||
#
|
||||
# def remove_attr(self, attr: str) -> None:
|
||||
# """删除frame元素attribute属性 \n
|
||||
# :param attr: 属性名
|
||||
# :return: None
|
||||
# """
|
||||
# self._inner_ele.remove_attr(attr)
|
||||
#
|
||||
# def parent(self, level_or_loc: Union[tuple, str, int] = 1) -> Union['ChromiumElement', None]:
|
||||
# """返回上面某一级父元素,可指定层数或用查询语法定位 \n
|
||||
# :param level_or_loc: 第几级父元素,或定位符
|
||||
# :return: 上级元素对象
|
||||
# """
|
||||
# return self._inner_ele.parent(level_or_loc)
|
||||
#
|
||||
# def prev(self,
|
||||
# filter_loc: Union[tuple, str] = '',
|
||||
# index: int = 1,
|
||||
# timeout: float = 0) -> Union['ChromiumElement', str, None]:
|
||||
# """返回前面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个 \n
|
||||
# :param filter_loc: 用于筛选元素的查询语法
|
||||
# :param index: 前面第几个查询结果元素
|
||||
# :param timeout: 查找元素的超时时间
|
||||
# :return: 兄弟元素
|
||||
# """
|
||||
# return self._inner_ele.prev(index, filter_loc, timeout)
|
||||
#
|
||||
# def next(self,
|
||||
# filter_loc: Union[tuple, str] = '',
|
||||
# index: int = 1,
|
||||
# timeout: float = 0) -> Union['ChromiumElement', str, None]:
|
||||
# """返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个 \n
|
||||
# :param filter_loc: 用于筛选元素的查询语法
|
||||
# :param index: 后面第几个查询结果元素
|
||||
# :param timeout: 查找元素的超时时间
|
||||
# :return: 兄弟元素
|
||||
# """
|
||||
# return self._inner_ele.next(index, filter_loc, timeout)
|
||||
#
|
||||
# def before(self,
|
||||
# filter_loc: Union[tuple, str] = '',
|
||||
# index: int = 1,
|
||||
# timeout: float = None) -> Union['ChromiumElement', str, None]:
|
||||
# """返回当前元素前面的一个元素,可指定筛选条件和第几个。查找范围不限兄弟元素,而是整个DOM文档 \n
|
||||
# :param filter_loc: 用于筛选元素的查询语法
|
||||
# :param index: 前面第几个查询结果元素
|
||||
# :param timeout: 查找元素的超时时间
|
||||
# :return: 本元素前面的某个元素或节点
|
||||
# """
|
||||
# return self._inner_ele.before(index, filter_loc, timeout)
|
||||
#
|
||||
# def after(self,
|
||||
# filter_loc: Union[tuple, str] = '',
|
||||
# index: int = 1,
|
||||
# timeout: float = None) -> Union['ChromiumElement', str, None]:
|
||||
# """返回当前元素后面的一个元素,可指定筛选条件和第几个。查找范围不限兄弟元素,而是整个DOM文档 \n
|
||||
# :param filter_loc: 用于筛选元素的查询语法
|
||||
# :param index: 后面第几个查询结果元素
|
||||
# :param timeout: 查找元素的超时时间
|
||||
# :return: 本元素后面的某个元素或节点
|
||||
# """
|
||||
# return self._inner_ele.after(index, filter_loc, timeout)
|
||||
#
|
||||
# def prevs(self,
|
||||
# filter_loc: Union[tuple, str] = '',
|
||||
# timeout: float = 0) -> List[Union['ChromiumElement', str]]:
|
||||
# """返回前面全部兄弟元素或节点组成的列表,可用查询语法筛选 \n
|
||||
# :param filter_loc: 用于筛选元素的查询语法
|
||||
# :param timeout: 查找元素的超时时间
|
||||
# :return: 兄弟元素或节点文本组成的列表
|
||||
# """
|
||||
# return self._inner_ele.prevs(filter_loc, timeout)
|
||||
#
|
||||
# def nexts(self,
|
||||
# filter_loc: Union[tuple, str] = '',
|
||||
# timeout: float = 0) -> List[Union['ChromiumElement', str]]:
|
||||
# """返回后面全部兄弟元素或节点组成的列表,可用查询语法筛选 \n
|
||||
# :param filter_loc: 用于筛选元素的查询语法
|
||||
# :param timeout: 查找元素的超时时间
|
||||
# :return: 兄弟元素或节点文本组成的列表
|
||||
# """
|
||||
# return self._inner_ele.nexts(filter_loc, timeout)
|
||||
#
|
||||
# def befores(self,
|
||||
# filter_loc: Union[tuple, str] = '',
|
||||
# timeout: float = None) -> List[Union['ChromiumElement', str]]:
|
||||
# """返回当前元素后面符合条件的全部兄弟元素或节点组成的列表,可用查询语法筛选。查找范围不限兄弟元素,而是整个DOM文档 \n
|
||||
# :param filter_loc: 用于筛选元素的查询语法
|
||||
# :param timeout: 查找元素的超时时间
|
||||
# :return: 本元素前面的元素或节点组成的列表
|
||||
# """
|
||||
# return self._inner_ele.befores(filter_loc, timeout)
|
||||
|
||||
|
||||
def make_chromium_ele(ele, loc, single=True, timeout=None, relative=True):
|
||||
"""在chromium元素中查找 \n
|
||||
:param ele: ChromiumElement对象
|
||||
@ -1481,6 +1243,8 @@ def run_script(page_or_ele, script, as_expr=False, timeout=None, args=None):
|
||||
if isinstance(page_or_ele, (ChromiumElement, ChromiumShadowRootElement)):
|
||||
page = page_or_ele.page
|
||||
obj_id = page_or_ele.obj_id
|
||||
# elif isinstance(page_or_ele, ChromiumFrame):
|
||||
# pass
|
||||
else:
|
||||
page = page_or_ele
|
||||
obj_id = page_or_ele._root_id
|
||||
@ -1527,8 +1291,11 @@ def _parse_js_result(page, ele, result):
|
||||
return None
|
||||
|
||||
elif sub_type == 'node':
|
||||
if result['className'] == 'ShadowRoot':
|
||||
class_name = result['className']
|
||||
if class_name == 'ShadowRoot':
|
||||
return ChromiumShadowRootElement(ele, obj_id=result['objectId'])
|
||||
elif class_name == 'HTMLDocument':
|
||||
return result
|
||||
else:
|
||||
return _make_chromium_ele(page, obj_id=result['objectId'])
|
||||
|
||||
|
@ -25,6 +25,7 @@ class ChromiumElement(DrissionElement):
|
||||
self.page: Union[ChromiumPage, WebPage] = ...
|
||||
self._node_id: str = ...
|
||||
self._obj_id: str = ...
|
||||
self._doc_id: str = ...
|
||||
self._scroll: ChromeScroll = ...
|
||||
self._select: ChromeSelect = ...
|
||||
|
||||
@ -59,6 +60,9 @@ class ChromiumElement(DrissionElement):
|
||||
@property
|
||||
def node_id(self) -> str: ...
|
||||
|
||||
@property
|
||||
def doc_id(self) -> str: ...
|
||||
|
||||
@property
|
||||
def size(self) -> dict: ...
|
||||
|
||||
@ -299,27 +303,27 @@ class ChromiumShadowRootElement(BaseElement):
|
||||
loc_or_str: Union[Tuple[str, str], str],
|
||||
timeout: float = ...) -> List[ChromiumElement]: ...
|
||||
|
||||
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 _ele(self,
|
||||
loc_or_str: Union[Tuple[str, str], str],
|
||||
timeout: float = ...,
|
||||
single: bool = ..., relative: bool =...) -> Union['ChromiumElement', None, List[ChromiumElement]]: ...
|
||||
single: bool = ..., relative: bool = ...) -> Union['ChromiumElement', None, List[ChromiumElement]]: ...
|
||||
|
||||
def _get_node_id(self, obj_id:str) -> str: ...
|
||||
def _get_node_id(self, obj_id: str) -> str: ...
|
||||
|
||||
def _get_obj_id(self, back_id:str) -> str: ...
|
||||
def _get_obj_id(self, back_id: str) -> str: ...
|
||||
|
||||
def _get_backend_id(self, node_id:str) -> str: ...
|
||||
def _get_backend_id(self, node_id: str) -> str: ...
|
||||
|
||||
|
||||
def make_chromium_ele(ele: ChromiumElement,
|
||||
loc: Union[str, Tuple[str, str]],
|
||||
single: bool = ...,
|
||||
timeout: float = ...,
|
||||
relative: bool =...) -> Union[ChromiumElement, str, None, List[Union[ChromiumElement, str]]]: ...
|
||||
relative: bool = ...) -> Union[ChromiumElement, str, None, List[Union[ChromiumElement, str]]]: ...
|
||||
|
||||
|
||||
def _find_by_xpath(ele: ChromiumElement,
|
||||
@ -341,7 +345,8 @@ def _make_chromium_ele(page: ChromiumBase, node_id: str = ..., obj_id: str = ...
|
||||
def _make_js_for_find_ele_by_xpath(xpath: str, type_txt: str, node_txt: str) -> str: ...
|
||||
|
||||
|
||||
def run_script(page_or_ele: Union[ChromiumBase, ChromiumElement, ChromiumShadowRootElement], script: str, as_expr: bool = ...,
|
||||
def run_script(page_or_ele: Union[ChromiumBase, ChromiumElement, ChromiumShadowRootElement], script: str,
|
||||
as_expr: bool = ...,
|
||||
timeout: float = ..., args: tuple = ...) -> Any: ...
|
||||
|
||||
|
||||
|
@ -97,9 +97,8 @@ class ChromiumPage(ChromiumBase):
|
||||
@property
|
||||
def tabs(self):
|
||||
"""返回所有标签页id"""
|
||||
self._driver
|
||||
json = self._control_session.get(f'http://{self.address}/json').json()
|
||||
return [i['id'] for i in json if i['type'] == 'page']
|
||||
tabs = self.run_cdp('Target.getTargets', filter=[{'type': "page"}])['targetInfos']
|
||||
return [i['targetId'] for i in tabs]
|
||||
|
||||
@property
|
||||
def process_id(self):
|
||||
|
@ -34,7 +34,7 @@ class ChromiumPage(ChromiumBase):
|
||||
def tabs_count(self) -> int: ...
|
||||
|
||||
@property
|
||||
def tabs(self) -> list: ...
|
||||
def tabs(self) -> List[str]: ...
|
||||
|
||||
@property
|
||||
def process_id(self) -> Union[None, int]: ...
|
||||
|
@ -285,7 +285,7 @@ def make_session_ele(html_or_ele, loc=None, single=True):
|
||||
|
||||
loc = loc[0], loc_str
|
||||
|
||||
elif isinstance(html_or_ele, DrissionElement): # DriverElement
|
||||
elif isinstance(html_or_ele, DrissionElement): # ChromiumElement, DriverElement
|
||||
loc_str = loc[1]
|
||||
if loc[0] == 'xpath' and loc[1].lstrip().startswith('/'):
|
||||
loc_str = f'.{loc[1]}'
|
||||
@ -296,7 +296,11 @@ def make_session_ele(html_or_ele, loc=None, single=True):
|
||||
# 获取整个页面html再定位到当前元素,以实现查找上级元素
|
||||
page = html_or_ele.page
|
||||
xpath = html_or_ele.xpath
|
||||
html_or_ele = fromstring(html_or_ele.page.html)
|
||||
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']
|
||||
else:
|
||||
html = html_or_ele.page.html
|
||||
html_or_ele = fromstring(html)
|
||||
html_or_ele = html_or_ele.xpath(xpath)[0]
|
||||
|
||||
elif isinstance(html_or_ele, BasePage): # MixPage, DriverPage 或 SessionPage
|
||||
|
@ -17,12 +17,19 @@ class SessionPage(BasePage):
|
||||
"""SessionPage封装了页面操作的常用功能,使用requests来获取、解析网页"""
|
||||
|
||||
def __init__(self, session_or_options=None, timeout=10):
|
||||
"""初始化函数"""
|
||||
"""初始化 \n
|
||||
:param session_or_options: Session对象或SessionOptions对象
|
||||
:param timeout: 连接超时时间
|
||||
"""
|
||||
super().__init__(timeout)
|
||||
self._response = None
|
||||
self._create_session(session_or_options)
|
||||
|
||||
def _create_session(self, Session_or_Options):
|
||||
"""创建内建Session对象
|
||||
:param Session_or_Options: Session对象或SessionOptions对象
|
||||
:return: None
|
||||
"""
|
||||
if Session_or_Options is None or isinstance(Session_or_Options, SessionOptions):
|
||||
options = Session_or_Options or SessionOptions()
|
||||
self._set_session(options.as_dict())
|
||||
|
@ -1,7 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from functools import partial
|
||||
from json import dumps, loads
|
||||
from logging import getLogger
|
||||
|
@ -21,7 +21,7 @@ DrissionPage,即 driver 和 session 组合而成的 page。
|
||||
除了合并两者,本库还以网页为单位封装了常用功能,提供非常简便的操作和语句,在用于网页自动化操作时,减少考虑细节,专注功能实现,使用更方便。
|
||||
一切从简,尽量提供简单直接的使用方法,对新手更友好。
|
||||
|
||||
# 🔆 3.0 版隆重推出(测试中)
|
||||
# 🔆 3.0 版隆重推出
|
||||
|
||||
以前的版本是对 selenium 进行重新封装实现的。从 3.0 开始,作者另起炉灶,对底层进行了重新开发,摆脱对 selenium 的依赖,增强了功能,提升了运行效率。
|
||||
3.0 全新开发的页面对象是`WebPage`,支持 chromium 内核的浏览器(如 chrome 和 edge)。除了保持之前的功能,比依赖 selenium 的`MixPage`有以下优点:
|
||||
|
@ -47,9 +47,8 @@ page = MixPage('s')
|
||||
- ini_path:ini 文件路径,为`None`则读取默认 ini 文件
|
||||
|
||||
```python
|
||||
from Drission import MixPage
|
||||
# 导入 DriverOptions
|
||||
from DrissionPage.config import DriverOptions
|
||||
from DrissionPage import MixPage, DriverOptions
|
||||
|
||||
# 创建浏览器配置对象,从文件读取配置,并增加设置浏览器静音和不加载图片
|
||||
do = DriverOptions().set_mute().set_no_imgs()
|
||||
@ -59,23 +58,23 @@ page = MixPage(driver_options=do)
|
||||
|
||||
## `SessionOptions`类
|
||||
|
||||
`SessionOptions`用于管理创建浏览器时的配置,浏览器创建后再修改这个配置是没有效果的。
|
||||
`SessionOptions`对象能实现链式操作。
|
||||
`SessionOptions`用于管理创建`Session`对象时的配置,内置了常用的配置,并能实现链式操作。详细使用方法见“启动配置”一节。
|
||||
|
||||
初始化参数:
|
||||
|
||||
- read_file:是否从 ini 文件中读取配置信息
|
||||
- ini_path:ini 文件路径,为`None`则读取默认 ini 文件
|
||||
|
||||
!>**注意:**<br>`Session`对象创建后再修改这个配置是没有效果的。
|
||||
|
||||
```python
|
||||
from Drission import MixPage
|
||||
# 导入 SessionOptions
|
||||
from DrissionPage.config import SessionOptions
|
||||
# 导入 DriverOptions
|
||||
from DrissionPage import MixPage,SessionOptions
|
||||
|
||||
proxies = {'http': 'http://127.0.0.1:1080',
|
||||
'https': 'https://127.0.0.1:1080'}
|
||||
|
||||
# 创建浏览器配置对象,不从 ini 文件读取,并设置代理信息
|
||||
# 创建配置对象,不从 ini 文件读取,并设置代理信息
|
||||
so = SessionOptions(read_file=False).set_proxies(proxies)
|
||||
# 用该配置创建页面对象(s 模式)
|
||||
page = MixPage(mode='s', session_options=so)
|
||||
@ -89,8 +88,7 @@ page = MixPage(mode='s', session_options=so, driver_options=do)
|
||||
|
||||
# 传入`Drission`对象创建
|
||||
|
||||
在入门指南的基本概念一节里,我们讲过`Drission`对象相当于驱动器的角色。事实上,上述两种方式,`MixPage`都会自动创建一个`Drission`对象用于管理与网站或浏览器的连接,我们当然也可以手动创建并传入`MixPage`
|
||||
。
|
||||
在入门指南的基本概念一节里,我们讲过`Drission`对象相当于驱动器的角色。事实上,上述两种方式,`MixPage`都会自动创建一个`Drission`对象用于管理与网站或浏览器的连接,我们当然也可以手动创建并传入`MixPage`。
|
||||
`Drission`一般是不用手动创建的,要手动创建的时候,一般是用于i以下几种情况:
|
||||
|
||||
- 指定使用某个配置文件
|
||||
@ -120,7 +118,7 @@ page = MixPage(drission=d)
|
||||
多页面对象间共用驱动器,如多个`MixPage`控制一个浏览器:
|
||||
|
||||
```python
|
||||
from Drission import MixPage
|
||||
from DrissionPage import MixPage
|
||||
|
||||
page1 = MixPage()
|
||||
d = page1.drission
|
||||
|
@ -19,7 +19,7 @@ DrissionPage,即 driver 和 session 组合而成的 page。
|
||||
除了合并两者,本库还以网页为单位封装了常用功能,提供非常简便的操作和语句,在用于网页自动化操作时,减少考虑细节,专注功能实现,使用更方便。
|
||||
一切从简,尽量提供简单直接的使用方法,对新手更友好。
|
||||
|
||||
# 🔆 3.0 版隆重推出(测试中)
|
||||
# 🔆 3.0 版隆重推出
|
||||
|
||||
以前的版本是对 selenium 进行重新封装实现的。从 3.0 开始,作者另起炉灶,对底层进行了重新开发,摆脱对 selenium 的依赖,增强了功能,提升了运行效率。
|
||||
3.0 全新开发的页面对象是`WebPage`,支持 chromium 内核的浏览器(如 chrome 和 edge)。除了保持之前的功能,比依赖 selenium 的`MixPage`有以下优点:
|
||||
@ -34,9 +34,9 @@ DrissionPage,即 driver 和 session 组合而成的 page。
|
||||
|
||||
- 把 iframe 看作普通元素,获取后可直接在其中查找元素,逻辑更清晰
|
||||
|
||||
- 可以同时操作浏览器中的多个标签页,即使标签页为非激活状态
|
||||
- 可以同时操作浏览器中的多个标签页,即使标签页为非激活状态,无需切换
|
||||
|
||||
- 可以直接读取浏览器缓存来保持图片,无需用 GUI 点击保存
|
||||
- 可以直接读取浏览器缓存来保存图片,无需用 GUI 点击另存
|
||||
|
||||
- 可以对整个网页截图,包括视口外的部分(90以上版本浏览器支持)
|
||||
|
||||
|
@ -55,7 +55,7 @@ page.get('https://www.163.com', retry=1, interval=1, timeout=1.5)
|
||||
from DrissionPage import WebPage
|
||||
|
||||
page = WebPage()
|
||||
page.set_page_load_strategy.set_eager()
|
||||
page.set_page_load_strategy()
|
||||
```
|
||||
|
||||
# ✔️ s 模式
|
||||
|
@ -1,4 +1,4 @@
|
||||
本节介绍如何获取元素对象。
|
||||
本节介绍如何获取元素对象。可以从页面中查找元素,也可以在元素中查找子元素。
|
||||
|
||||
无论是数据采集还是页面自动化,定位元素都是重中之重的的技能,浏览器开发者工具虽然可以直接复制绝对 xpath 或 css 路径,但这样做一来代码繁琐,可读性低,二来难以应付动态变化的页面。
|
||||
本库提供一套简洁易用的语法,用于快速定位元素,并且内置等待功能、支持链式查找,减少了代码的复杂性。
|
||||
@ -13,6 +13,8 @@ d 模式的元素还有专门用于处理 shadow dom 的`shadow_root`属性。
|
||||
|
||||
# ✔️ 示例
|
||||
|
||||
先看一些示例,感性认识一下,后面在详细讲解用法。
|
||||
|
||||
## 📍 简单示例
|
||||
|
||||
```html
|
||||
@ -81,7 +83,8 @@ titles = ul_ele.eles('tag:a')
|
||||
for i in titles:
|
||||
print(i.text)
|
||||
|
||||
"""输出:
|
||||
"""
|
||||
输出:
|
||||
全部推荐项目
|
||||
前沿技术
|
||||
智能硬件
|
||||
@ -93,33 +96,41 @@ IOT/物联网/边缘计算
|
||||
|
||||
# ✔️ 查找元素方法
|
||||
|
||||
以下方法,既可用于在页面中查找元素,也可用于在元素中查找子元素。
|
||||
## 📍 查找单个元素
|
||||
|
||||
## ele()
|
||||
查找单个元素使用`ele()`方法。
|
||||
|
||||
此方法用于查找并返回第一个匹配的元素,d 模式下返回`ChromiumElement`,s 模式下返回`SessionElement`,用 xpath 获取元素属性时,直接返回属性文本。查找不到结果则返回`None`。
|
||||
页面对象和元素对象都拥有此方法,用于查找第一个匹配条件的元素。
|
||||
d 模式下返回`ChromiumElement`对象,s 模式下返回`SessionElement`对象,没有找到返回`None`。
|
||||
在元素下查找子元素时,还可以用 xpath 获取元素属性,直接返回属性文本。
|
||||
页面对象和元素对象的`ele()`方法参数名称稍有不同,但用法一样。
|
||||
|
||||
参数:
|
||||
|
||||
- loc_or_str(元素对象拥有):元素的定位信息,可以是 loc 元组,或查询字符串
|
||||
- loc_or_ele(页面对象拥有):元素的定位信息,可以是元素对象,loc 元组,或查询字符串
|
||||
- loc_or_str(元素对象):元素的定位信息,可以是 loc 元组,或查询字符串
|
||||
- loc_or_ele(页面对象):元素的定位信息,可以是元素对象,loc 元组,或查询字符串
|
||||
- timeout:查找元素超时时间,默认与元素所在页面等待时间一致,s 模式下无效
|
||||
|
||||
返回:s 模式下返回`SessionElement`,d 模式下返回`DriverElement`,或用 xpath 获取到的属性值
|
||||
返回:s 模式下返回`SessionElement`,d 模式下返回`ChromiumElement`;或用 xpath 获取到的属性值
|
||||
|
||||
```python
|
||||
from DrissionPage import WebPage
|
||||
|
||||
page = WebPage()
|
||||
|
||||
# 在页面内查找元素
|
||||
ele1 = page.ele('search text')
|
||||
|
||||
# 在元素内查找后代元素
|
||||
ele2 = ele1.ele('search text')
|
||||
|
||||
|
||||
# 使用 xpath 获取后代中第一个 div 元素的 class 属性
|
||||
class = ele1.ele('xpath://div/@class')
|
||||
# 使用 xpath 获取后代中第一个 div 元素的 class 属性(元素内查找可用)
|
||||
ele_class = ele1.ele('xpath://div/@class')
|
||||
```
|
||||
|
||||
## eles()
|
||||
## 📍 查找多个元素
|
||||
|
||||
查找多个元素使用`eles()`方法。
|
||||
|
||||
此方法与`ele()`相似,但返回的是匹配到的所有元素组成的列表,用 xpath 获取元素属性时,返回属性文本组成的列表。
|
||||
|
||||
@ -128,7 +139,7 @@ class = ele1.ele('xpath://div/@class')
|
||||
- loc_or_str:元素的定位信息,可以是 loc 元组,或查询字符串
|
||||
- timeout:查找元素超时时间,默认与元素所在页面等待时间一致,s 模式下无效
|
||||
|
||||
返回:s 模式下返回`SessionElement`组成的列表,d 模式下返回`DriverElement`组成的列表,或用 xpath 获取到的属性值组成的列表
|
||||
返回:s 模式下返回`SessionElement`组成的列表,d 模式下返回`ChromiumElement`组成的列表;或用 xpath 获取到的属性值组成的列表
|
||||
|
||||
```python
|
||||
# 获取 ele 元素内的所有 p 元素
|
||||
@ -137,7 +148,18 @@ p_eles = ele.eles('tag:p')
|
||||
print(p_eles[0])
|
||||
```
|
||||
|
||||
## s_ele()
|
||||
## 📍 查找单个静态元素
|
||||
|
||||
静态元素即 s 模式的`SessionElement`元素对象,是纯文本构造的,因此用它处理速度非常快速。对于复杂的页面,要在成百上千个元素中采集数据时,转换为静态元素可把速度提升几个数量级。作者曾在采集的时候,用同一套逻辑,仅仅把元素转换为静态,就把一个要 30 秒才采集 完成的页面,加速到零点几秒完成。
|
||||
我们甚至可以把整个页面转换为静态元素,再在其中提取信息。
|
||||
当然,这种元素不能进行点击等交互。
|
||||
s 模式下,所有元素本身就是静态元素,d 模式下,用`s_ele()`可在把查找到的动态元素转换为静态元素输出,或者获取元素或页面本身的静态元素副本。
|
||||
|
||||
`s_ele()`方法
|
||||
|
||||
页面对象和元素对象都拥有此方法,用于查找第一个匹配条件的元素,获取其静态版本。
|
||||
|
||||
页面对象和元素对象的`s_ele()`方法参数名称稍有不同,但用法一样。
|
||||
|
||||
此方法用于在一个元素下查找后代元素,以`SessionElement`形式返回结果(xpath 获取属性值时依然是返回`str`),也可以直接将一个元素或页面转换为`SessionElement`版本。
|
||||
|
||||
@ -147,24 +169,39 @@ s 模式下这个方法和`ele()`是一样的。
|
||||
|
||||
参数:
|
||||
|
||||
- loc_or_str(元素对象拥有):元素的定位信息,可以是 loc 元组,或查询字符串。为`None`时直接返回当前元素的`SessionElemnet`版本
|
||||
- loc_or_ele(页面对象拥有):元素的定位信息,可以是 loc 元组,或查询字符串。为`None`时直接返回当前页面的 `SessionElemnet`版本
|
||||
- loc_or_str(元素对象):元素的定位信息,可以是 loc 元组,或查询字符串。为`None`时直接返回当前元素的`SessionElemnet`版本
|
||||
- loc_or_ele(页面对象):元素的定位信息,可以是 loc 元组,或查询字符串。为`None`时直接返回当前页面的 `SessionElemnet`版本
|
||||
|
||||
返回:`SessionElement`,或用 xpath 获取到的属性值
|
||||
|
||||
!>**注意:**<br>页面对象和元素对象的`s_ele()`方法不能搜索到在 frame 里的元素,页面对象的静态版本也不能搜索 frame 里的元素。要使用 frame 里元素的静态版本,可先获取该元素,再转换。而使用`ChromiumFrame`对象,则可以直接用`s_ele()`查找元素,这在后面章节再讲述。
|
||||
|
||||
```python
|
||||
# 获取元素或页面的的 SessionElement 版本
|
||||
ele2 = ele1.s_ele()
|
||||
ele2 = page.s_ele()
|
||||
from DrissionPage import WebPage
|
||||
|
||||
# 在 ele1 元素下查找元素,并以 SessionElemnet 返回
|
||||
ele2 = ele1.s_ele('search text')
|
||||
p = WebPage()
|
||||
|
||||
# 在页面下查找元素,并以 SessionElemnet 返回
|
||||
ele = page.s_ele('search text')
|
||||
# 在页面中查找元素,获取其静态版本
|
||||
ele1 = page.s_ele('search text')
|
||||
|
||||
# 在动态元素中查找元素,获取其静态版本
|
||||
ele = page.ele('search text')
|
||||
ele2 = ele.s_ele()
|
||||
|
||||
# 获取页面元素的静态副本(不传入参数)
|
||||
s_page = page.s_ele()
|
||||
|
||||
# 获取动态元素的静态副本
|
||||
s_ele = ele.s_ele()
|
||||
|
||||
# 在静态副本中查询下级元素(因为已经是静态元素,用ele()查找结果也是静态)
|
||||
ele3 = s_page.ele('search text')
|
||||
ele4 = s_ele.ele('search text')
|
||||
```
|
||||
|
||||
## s_eles()
|
||||
## 📍 查找多个静态元素
|
||||
|
||||
查找多个静态元素使用`s_eles()`方法。
|
||||
|
||||
此方法与`s_ele()`相似,但返回的是匹配到的所有元素组成的列表,或属性值组成的列表。
|
||||
|
||||
@ -174,19 +211,26 @@ ele = page.s_ele('search text')
|
||||
|
||||
返回:`SessionElement`组成的列表,或用 xpath 获取到的属性值组成的列表
|
||||
|
||||
## active_ele
|
||||
```python
|
||||
from DrissionPage import WebPage
|
||||
|
||||
该属性返回当前页面焦点所在元素。d 模式独有。
|
||||
p = WebPage()
|
||||
for ele in p.s_eles('search text'):
|
||||
print(ele.text)
|
||||
```
|
||||
|
||||
## 📍 获取当前焦点元素
|
||||
|
||||
使用方法`active_ele()`获取页面上焦点所在元素,为 d 模式独有。
|
||||
|
||||
```python
|
||||
ele = page.active_ele
|
||||
```
|
||||
|
||||
## shadow_root
|
||||
## 📍 获取 shadow_root
|
||||
|
||||
`DriverElement`元素除了以上方法和属性外,还有`shadow_root`属性,用于获取其内部的 shadow_root 元素。
|
||||
该属性返回的是一个`ShadowRootElement`,类似于`DriverElement`,功能比`DriverElement`少。但也有`ele()`和`eles()`方法,可直接搜索其下的元素,返回 `DriverElement`
|
||||
元素。返回的`DriverElement`和普通的没有区别。
|
||||
d 模式元素如果包含 shadow_root,可使用`shadow_root`属性获取。
|
||||
该属性返回的是一个`ChromiumShadowRootElement`对象,用法与`ChromiumElement`相似。也能使用各种元素查找方式,返回内部元素或相对位置元素,返回 `ChromiumElement`元素。返回的`ChromiumElement`和普通的没有区别。
|
||||
|
||||
```python
|
||||
# 获取一个元素下是 shadow root
|
||||
@ -281,8 +325,7 @@ ele2 = ele1.ele('css:div[abc\@def="v"]')
|
||||
|
||||
- 属性名本身以`-`开头
|
||||
|
||||
!> **注意:**
|
||||
如果属性中包含特殊字符,如包含`@`,用这个方式不能正确匹配到,须使用 css selector 方式查找。且特殊字符要用`\`转义。
|
||||
!> **注意:**:<br>如果属性中包含特殊字符,如包含`@`,用这个方式不能正确匹配到,须使用 css selector 方式查找。且特殊字符要用`\`转义。
|
||||
|
||||
```python
|
||||
# 查找 name 属性为 name 且 class 属性包含 cls 文本的元素
|
||||
@ -400,9 +443,7 @@ ele2 = ele1.ele('xpath://div')
|
||||
txt = ele1.ele('xpath://div/@class')
|
||||
```
|
||||
|
||||
?> **Tips:** <br>
|
||||
查找元素的后代时,selenium 原生代码要求 xpath 前面必须加`.`,否则会变成在全个页面中查找。笔者觉得这个设计是画蛇添足,既然已经通过元素查找了,自然应该只查找这个元素内部的元素。所以,用 xpath
|
||||
在元素下查找时,最前面`//`或`/`前面的`.`可以省略。
|
||||
?> **Tips:** <br>查找元素的后代时,selenium 原生代码要求 xpath 前面必须加`.`,否则会变成在全个页面中查找。作者觉得这个设计是画蛇添足,既然已经通过元素查找了,自然应该只查找这个元素内部的元素。所以,用 xpath 在元素下查找时,最前面`//`或`/`前面的`.`可以省略。
|
||||
|
||||
## 📍 selenium 的 loc 元组
|
||||
|
||||
@ -445,9 +486,9 @@ ele2 = ele1.ele('some text', timeout=1)
|
||||
以下方法可以以某元素为基准,在 DOM 中按照条件获取其兄弟元素、祖先元素、文档前后元素。
|
||||
除获取元素外,还能通过 xpath 获取任意节点内容,如文本节点、注释节点。这在处理元素和文本节点混排的时候非常有用。
|
||||
|
||||
## parent()
|
||||
## 📍 获取父级元素
|
||||
|
||||
此方法获取当前元素某一级父元素,可指定筛选条件或层数。
|
||||
`parent()`方法获取当前元素某一级父元素,可指定筛选条件或层数。
|
||||
|
||||
参数:
|
||||
|
||||
@ -463,14 +504,14 @@ ele2 = ele1.parent(2)
|
||||
ele2 = ele1.parent('#id1')
|
||||
```
|
||||
|
||||
## next()
|
||||
## 📍 获取后面单个兄弟元素
|
||||
|
||||
此方法返回当前元素后面的某一个兄弟元素,可指定筛选条件和第几个。
|
||||
`next()`方法返回当前元素后面的某一个同级元素,可指定筛选条件和第几个。
|
||||
|
||||
参数:
|
||||
|
||||
- index:查询结果中的第几个
|
||||
- filter_loc:用于筛选元素的查询语法
|
||||
- index:查询结果中的第几个
|
||||
- timeout:查找元素的超时时间
|
||||
|
||||
返回:本元素后面某个兄弟元素或节点文本
|
||||
@ -483,15 +524,15 @@ ele2 = ele1.next()
|
||||
ele2 = ele1.next(3)
|
||||
|
||||
# 获取 ele1 后面第 3 个 div 兄弟元素
|
||||
ele2 = ele1.next(3, 'tag:div')
|
||||
ele2 = ele1.next('tag:div', 3)
|
||||
|
||||
# 获取 ele1 后面第一个文本节点的文本
|
||||
txt = ele1.next(1, 'xpath:text()')
|
||||
txt = ele1.next('xpath:text()', 1)
|
||||
```
|
||||
|
||||
## nexts()
|
||||
## 📍 获取后面多个兄弟元素
|
||||
|
||||
此方法返回后面全部符合条件的兄弟元素或节点组成的列表,可用查询语法筛选。
|
||||
`nexts()`方法返回当前元素后面全部符合条件的同级元素或节点组成的列表,可用查询语法筛选。
|
||||
|
||||
参数:
|
||||
|
||||
@ -511,14 +552,14 @@ divs = ele1.nexts('tag:div')
|
||||
txts = ele1.nexts('xpath:text()')
|
||||
```
|
||||
|
||||
## prev()
|
||||
## 📍 获取前面单个兄弟元素
|
||||
|
||||
此方法返回当前元素前面的某一个兄弟元素,可指定筛选条件和第几个。
|
||||
`prev()`方法返回当前元素前面的某一个同级元素,可指定筛选条件和第几个。
|
||||
|
||||
参数:
|
||||
|
||||
- index:查询结果中的第几个
|
||||
- filter_loc:用于筛选元素的查询语法
|
||||
- index:查询结果中的第几个
|
||||
- timeout:查找元素的超时时间
|
||||
|
||||
返回:本元素前面某个兄弟元素或节点文本
|
||||
@ -537,9 +578,9 @@ ele2 = ele1.prev(3, 'tag:div')
|
||||
txt = ele1.prev(1, 'xpath:text()')
|
||||
```
|
||||
|
||||
## prevs()
|
||||
## 📍 获取前面多个兄弟元素
|
||||
|
||||
此方法返回前面全部符合条件的兄弟元素或节点组成的列表,可用查询语法筛选。
|
||||
`prevs()`方法返回当前元素前面全部符合条件的同级元素或节点组成的列表,可用查询语法筛选。
|
||||
|
||||
参数:
|
||||
|
||||
@ -556,14 +597,14 @@ eles = ele1.prevs()
|
||||
divs = ele1.prevs('tag:div')
|
||||
```
|
||||
|
||||
## after()
|
||||
## 📍 在后面文档中查找单个元素
|
||||
|
||||
此方法返回当前元素后面的某一个元素,可指定筛选条件和第几个。这个方法查找范围不局限在兄弟元素间,而是整个 DOM 文档。
|
||||
`after()`方法返回当前元素后面的某一个元素,可指定筛选条件和第几个。这个方法查找范围不局限在兄弟元素间,而是整个 DOM 文档。
|
||||
|
||||
参数:
|
||||
|
||||
- index:查询结果中的第几个
|
||||
- filter_loc:用于筛选元素的查询语法
|
||||
- index:查询结果中的第几个
|
||||
- timeout:查找元素的超时时间
|
||||
|
||||
返回:本元素后面某个元素或节点
|
||||
@ -573,15 +614,15 @@ divs = ele1.prevs('tag:div')
|
||||
ele2 = ele1.after(3)
|
||||
|
||||
# 获取 ele1 后面第 3 个 div 元素
|
||||
ele2 = ele1.after(3, 'tag:div')
|
||||
ele2 = ele1.after('tag:div', 3)
|
||||
|
||||
# 获取 ele1 后面第一个文本节点的文本
|
||||
txt = ele1.after(1, 'xpath:text()')
|
||||
txt = ele1.after('xpath:text()', 1)
|
||||
```
|
||||
|
||||
## afters()
|
||||
## 📍 在后面文档中查找多个元素
|
||||
|
||||
此方法返回后面符合条件的全部元素或节点组成的列表,可用查询语法筛选。这个方法查找范围不局限在兄弟元素间,而是整个 DOM 文档。
|
||||
`afters()`方法返回当前元素后面符合条件的全部元素或节点组成的列表,可用查询语法筛选。这个方法查找范围不局限在兄弟元素间,而是整个 DOM 文档。
|
||||
|
||||
参数:
|
||||
|
||||
@ -598,14 +639,14 @@ eles = ele1.afters()
|
||||
divs = ele1.afters('tag:div')
|
||||
```
|
||||
|
||||
## before()
|
||||
## 📍 在前面文档中查找单个元素
|
||||
|
||||
此方法返回当前元素前面的某一个元素,可指定筛选条件和第几个。这个方法查找范围不局限在兄弟元素间,而是整个 DOM 文档。
|
||||
`before()`方法返回当前元素前面的某一个元素,可指定筛选条件和第几个。这个方法查找范围不局限在兄弟元素间,而是整个 DOM 文档。
|
||||
|
||||
参数:
|
||||
|
||||
- index:查询结果中的第几个
|
||||
- filter_loc:用于筛选元素的查询语法
|
||||
- index:查询结果中的第几个
|
||||
- timeout:查找元素的超时时间
|
||||
|
||||
返回:本元素前面某个元素或节点
|
||||
@ -615,15 +656,15 @@ divs = ele1.afters('tag:div')
|
||||
ele2 = ele1.before(3)
|
||||
|
||||
# 获取 ele1 前面第 3 个 div 元素
|
||||
ele2 = ele1.before(3, 'tag:div')
|
||||
ele2 = ele1.before('tag:div', 3)
|
||||
|
||||
# 获取 ele1 前面第一个文本节点的文本
|
||||
txt = ele1.before(1, 'xpath:text()')
|
||||
txt = ele1.before('xpath:text()', 1)
|
||||
```
|
||||
|
||||
## befores()
|
||||
## 📍 在前面文档中查找多个元素
|
||||
|
||||
此方法返回前面全部符合条件的元素或节点组成的列表,可用查询语法筛选。这个方法查找范围不局限在兄弟元素间,而是整个 DOM 文档。
|
||||
`befores()`方法返回当前元素前面全部符合条件的元素或节点组成的列表,可用查询语法筛选。这个方法查找范围不局限在兄弟元素间,而是整个 DOM 文档。
|
||||
|
||||
参数:
|
||||
|
||||
@ -640,14 +681,18 @@ eles = ele1.befores()
|
||||
divs = ele1.befores('tag:div')
|
||||
```
|
||||
|
||||
# ✔️ 查找 frame 里的元素
|
||||
|
||||
与 selenium 不同,本库可以直接查找 frame 里面的元素,而无需切入切出,大大简化了程序逻辑,使用更便捷。
|
||||
|
||||
未完待续。。。
|
||||
|
||||
# ✔️ `ShadowRootElement`相关查找
|
||||
|
||||
本库把 shadow-root 也作为元素对象看待,是为`ShadowRootElement`对象。对`ShadowRootElement`对象可与普通元素一样查找下级元素和 DOM 内相对定位,但不能用页面布局相对定位。
|
||||
对`ShadowRootElement`对象进行相对定位时,把它看作其父对象内部的第一个对象,其余定位逻辑与普通对象一致。
|
||||
本库把 shadow-root 也作为元素对象看待,是为`ChromiumShadowRootElement`对象。该对象可与普通元素一样查找下级元素和 DOM 内相对定位。
|
||||
对`ChromiumShadowRootElement`对象进行相对定位时,把它看作其父对象内部的第一个对象,其余定位逻辑与普通对象一致。
|
||||
|
||||
!> **注意:** <br>
|
||||
如果`ShadowRootElement`元素的下级元素中有其它`ShadowRootElement`元素,那这些下级`ShadowRootElement`
|
||||
元素内部是无法直接通过定位语句查找到的,只能先定位到其父元素,再用`shadow-root`属性获取。
|
||||
!> **注意:** <br>如果`ChromiumShadowRootElement`元素的下级元素中有其它`ChromiumShadowRootElement`元素,那这些下级`ChromiumShadowRootElement`元素内部是无法直接通过定位语句查找到的,只能先定位到其父元素,再用`shadow-root`属性获取。
|
||||
|
||||
```python
|
||||
# 获取一个 shadow-root 元素
|
||||
@ -658,8 +703,8 @@ ele1 = sr_ele.ele('tag:div')
|
||||
|
||||
# 用相对定位获取其它元素
|
||||
ele1 = sr_ele.parent(2)
|
||||
ele1 = sr_ele.next(1, 'tag:div')
|
||||
ele1 = sr_ele.after(1, 'tag:div')
|
||||
ele1 = sr_ele.next('tag:div', 1)
|
||||
ele1 = sr_ele.after('tag:div', 1)
|
||||
eles = sr_ele.nexts('tag:div')
|
||||
|
||||
# 定位下级元素中的 shadow+-root 元素
|
||||
@ -701,8 +746,8 @@ ele2 = ele1('x://div[@class="ele_class"]')
|
||||
| css | c |
|
||||
| shadow_root | sr |
|
||||
|
||||
# Tips
|
||||
# ✔️ Tips
|
||||
|
||||
- 从一个`DriverElement`元素获取到的`SessionElement`版本,依然能够使用相对定位方法定位祖先或兄弟元素。
|
||||
- 从一个`ChromiumElement`元素获取到的`SessionElement`版本,依然能够使用相对定位方法定位祖先或兄弟元素。但如果元素在 frame 中,相对定位不能超越 frame 文档。
|
||||
- `SessionElement`和`SessionPage`的`ele()`和`eles()`方法也有`timeout`参数,但它是不生效的,仅用于保持与 d 模式元素书写一致,便于无差别的调用。
|
||||
- 定位语句内容与关键字重复时,请使用 xpath 或 css selector 代替。
|
||||
|
Loading…
x
Reference in New Issue
Block a user