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