基本完成download设置,待测试

This commit is contained in:
g1879 2023-01-19 11:26:35 +08:00
parent 62b83b0749
commit 17ae5e83b1
10 changed files with 140 additions and 116 deletions

View File

@ -29,10 +29,6 @@ class ChromiumBase(BasePage):
self._root_id = None
self._debug = False
self._debug_recorder = None
self._control_session = Session()
self._control_session.keep_alive = False
self._first_run = True
self._is_reading = False # 用于避免不同线程重复读取document
self._timeouts = None
self._page_load_strategy = None
@ -47,6 +43,7 @@ class ChromiumBase(BasePage):
:param tab_id: 要控制的标签页id不指定默认为激活的
:return: None
"""
self._chromium_init()
self.address = addr_driver_opts
if not tab_id:
json = self._control_session.get(f'http://{self.address}/json').json()
@ -56,6 +53,12 @@ class ChromiumBase(BasePage):
self._get_document()
self._first_run = False
def _chromium_init(self):
self._control_session = Session()
self._control_session.keep_alive = False
self._first_run = True
self._is_reading = False
def _set_options(self):
"""用于设置浏览器运行参数"""
self._timeouts = Timeout(self)

View File

@ -41,6 +41,8 @@ class ChromiumBase(BasePage):
addr_driver_opts: Union[str, ChromiumDriver, DriverOptions] = None,
tab_id: str = None) -> None: ...
def _chromium_init(self): ...
def _init_page(self, tab_id: str = None) -> None: ...
def _get_document(self) -> None: ...

View File

@ -21,7 +21,7 @@ class ChromiumElement(DrissionElement):
"""ChromePage页面对象中的元素对象"""
def __init__(self, page, node_id=None, obj_id=None, backend_id=None):
"""初始化node_id和obj_id必须至少传入一个 \n
"""初始化node_id和obj_id必须至少传入一个
:param page: 元素所在ChromePage页面对象
:param node_id: cdp中的node id
:param obj_id: js中的object id
@ -56,8 +56,8 @@ class ChromiumElement(DrissionElement):
return f'<ChromiumElement {self.tag} {" ".join(attrs)}>'
def __call__(self, loc_or_str, timeout=None):
"""在内部查找元素 \n
ele2 = ele1('@id=ele_id') \n
"""在内部查找元素
ele2 = ele1('@id=ele_id')
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 超时时间
:return: ChromiumElement对象或属性文本
@ -86,8 +86,7 @@ class ChromiumElement(DrissionElement):
def attrs(self):
"""返回元素所有attribute属性"""
attrs = self.page.run_cdp('DOM.getAttributes', nodeId=self._node_id, not_change=True)['attributes']
attrs_len = len(attrs)
return {attrs[i]: attrs[i + 1] for i in range(0, attrs_len, 2)}
return {attrs[i]: attrs[i + 1] for i in range(0, len(attrs), 2)}
@property
def text(self):
@ -197,14 +196,14 @@ class ChromiumElement(DrissionElement):
return self._scroll
def parent(self, level_or_loc=1):
"""返回上面某一级父元素,可指定层数或用查询语法定位 \n
"""返回上面某一级父元素,可指定层数或用查询语法定位
:param level_or_loc: 第几级父元素或定位符
:return: 上级元素对象
"""
return super().parent(level_or_loc)
def prev(self, filter_loc='', index=1, timeout=0):
"""返回前面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个 \n
"""返回前面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选元素的查询语法
:param index: 前面第几个查询结果元素
:param timeout: 查找元素的超时时间
@ -213,7 +212,7 @@ class ChromiumElement(DrissionElement):
return super().prev(index, filter_loc, timeout)
def next(self, filter_loc='', index=1, timeout=0):
"""返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个 \n
"""返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选元素的查询语法
:param index: 后面第几个查询结果元素
:param timeout: 查找元素的超时时间
@ -222,7 +221,7 @@ class ChromiumElement(DrissionElement):
return super().next(index, filter_loc, timeout)
def before(self, filter_loc='', index=1, timeout=None):
"""返回当前元素前面的一个元素可指定筛选条件和第几个。查找范围不限兄弟元素而是整个DOM文档 \n
"""返回当前元素前面的一个元素可指定筛选条件和第几个。查找范围不限兄弟元素而是整个DOM文档
:param filter_loc: 用于筛选元素的查询语法
:param index: 前面第几个查询结果元素
:param timeout: 查找元素的超时时间
@ -231,7 +230,7 @@ class ChromiumElement(DrissionElement):
return super().before(index, filter_loc, timeout)
def after(self, filter_loc='', index=1, timeout=None):
"""返回当前元素后面的一个元素可指定筛选条件和第几个。查找范围不限兄弟元素而是整个DOM文档 \n
"""返回当前元素后面的一个元素可指定筛选条件和第几个。查找范围不限兄弟元素而是整个DOM文档
:param filter_loc: 用于筛选元素的查询语法
:param index: 后面第几个查询结果元素
:param timeout: 查找元素的超时时间
@ -240,7 +239,7 @@ class ChromiumElement(DrissionElement):
return super().after(index, filter_loc, timeout)
def prevs(self, filter_loc='', timeout=0):
"""返回前面全部兄弟元素或节点组成的列表,可用查询语法筛选 \n
"""返回前面全部兄弟元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选元素的查询语法
:param timeout: 查找元素的超时时间
:return: 兄弟元素或节点文本组成的列表
@ -248,7 +247,7 @@ class ChromiumElement(DrissionElement):
return super().prevs(filter_loc, timeout)
def nexts(self, filter_loc='', timeout=0):
"""返回后面全部兄弟元素或节点组成的列表,可用查询语法筛选 \n
"""返回后面全部兄弟元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选元素的查询语法
:param timeout: 查找元素的超时时间
:return: 兄弟元素或节点文本组成的列表
@ -256,7 +255,7 @@ class ChromiumElement(DrissionElement):
return super().nexts(filter_loc, timeout)
def befores(self, filter_loc='', timeout=None):
"""返回当前元素后面符合条件的全部兄弟元素或节点组成的列表可用查询语法筛选。查找范围不限兄弟元素而是整个DOM文档 \n
"""返回当前元素后面符合条件的全部兄弟元素或节点组成的列表可用查询语法筛选。查找范围不限兄弟元素而是整个DOM文档
:param filter_loc: 用于筛选元素的查询语法
:param timeout: 查找元素的超时时间
:return: 本元素前面的元素或节点组成的列表
@ -264,7 +263,7 @@ class ChromiumElement(DrissionElement):
return super().befores(filter_loc, timeout)
def afters(self, filter_loc='', timeout=None):
"""返回当前元素后面符合条件的全部兄弟元素或节点组成的列表可用查询语法筛选。查找范围不限兄弟元素而是整个DOM文档 \n
"""返回当前元素后面符合条件的全部兄弟元素或节点组成的列表可用查询语法筛选。查找范围不限兄弟元素而是整个DOM文档
:param filter_loc: 用于筛选元素的查询语法
:param timeout: 查找元素的超时时间
:return: 本元素前面的元素或节点组成的列表
@ -272,7 +271,7 @@ class ChromiumElement(DrissionElement):
return super().afters(filter_loc, timeout)
def wait_ele(self, loc_or_ele, timeout=None):
"""返回用于等待子元素到达某个状态的等待器对象 \n
"""返回用于等待子元素到达某个状态的等待器对象
:param loc_or_ele: 可以是元素查询字符串loc元组
:param timeout: 等待超时时间
:return: 用于等待的ElementWaiter对象
@ -323,7 +322,7 @@ class ChromiumElement(DrissionElement):
return location_in_viewport(self.page, x, y) if x else False
def attr(self, attr):
"""返回attribute属性值 \n
"""返回attribute属性值
:param attr: 属性名
:return: 属性值文本没有该属性返回None
"""
@ -354,7 +353,7 @@ class ChromiumElement(DrissionElement):
return attrs.get(attr, None)
def set_attr(self, attr, value):
"""设置元素attribute属性 \n
"""设置元素attribute属性
:param attr: 属性名
:param value: 属性值
:return: None
@ -362,14 +361,14 @@ class ChromiumElement(DrissionElement):
self.run_js(f'this.setAttribute(arguments[0], arguments[1]);', False, attr, str(value))
def remove_attr(self, attr):
"""删除元素attribute属性 \n
"""删除元素attribute属性
:param attr: 属性名
:return: None
"""
self.run_js(f'this.removeAttribute("{attr}");')
def prop(self, prop):
"""获取property属性值 \n
"""获取property属性值
:param prop: 属性名
:return: 属性值文本
"""
@ -382,7 +381,7 @@ class ChromiumElement(DrissionElement):
return format_html(i['value']['value'])
def set_prop(self, prop, value):
"""设置元素property属性 \n
"""设置元素property属性
:param prop: 属性名
:param value: 属性值
:return: None
@ -391,14 +390,14 @@ class ChromiumElement(DrissionElement):
self.run_js(f'this.{prop}="{value}";')
def set_innerHTML(self, html):
"""设置元素innerHTML \n
"""设置元素innerHTML
:param html: html文本
:return: None
"""
self.set_prop('innerHTML', html)
def run_js(self, script, as_expr=False, *args):
"""运行javascript代码 \n
"""运行javascript代码
:param script: js文本
:param as_expr: 是否作为表达式运行为True时args无效
:param args: 参数按顺序在js文本中对应argument[0]argument[1]...
@ -407,7 +406,7 @@ class ChromiumElement(DrissionElement):
return run_js(self, script, as_expr, self.page.timeouts.script, args, True)
def run_async_js(self, script, as_expr=False, *args):
"""以异步方式执行js代码 \n
"""以异步方式执行js代码
:param script: js文本
:param as_expr: 是否作为表达式运行为True时args无效
:param args: 参数按顺序在js文本中对应argument[0]argument[2]...
@ -417,7 +416,7 @@ class ChromiumElement(DrissionElement):
Thread(target=run_js, args=(self, script, as_expr, self.page.timeouts.script, args, True)).start()
def ele(self, loc_or_str, timeout=None):
"""返回当前元素下级符合条件的第一个元素、属性或节点文本 \n
"""返回当前元素下级符合条件的第一个元素、属性或节点文本
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:return: ChromiumElement对象或属性文本
@ -425,7 +424,7 @@ class ChromiumElement(DrissionElement):
return self._ele(loc_or_str, timeout)
def eles(self, loc_or_str, timeout=None):
"""返回当前元素下级所有符合条件的子元素、属性或节点文本 \n
"""返回当前元素下级所有符合条件的子元素、属性或节点文本
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:return: ChromiumElement对象或属性文本组成的列表
@ -433,7 +432,7 @@ class ChromiumElement(DrissionElement):
return self._ele(loc_or_str, timeout=timeout, single=False)
def s_ele(self, loc_or_str=None):
"""查找第一个符合条件的元素以SessionElement形式返回处理复杂页面时效率很高 \n
"""查找第一个符合条件的元素以SessionElement形式返回处理复杂页面时效率很高
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:return: SessionElement对象或属性文本
"""
@ -442,7 +441,7 @@ class ChromiumElement(DrissionElement):
return make_session_ele(self, loc_or_str)
def s_eles(self, loc_or_str=None):
"""查找所有符合条件的元素以SessionElement列表形式返回 \n
"""查找所有符合条件的元素以SessionElement列表形式返回
:param loc_or_str: 定位符
:return: SessionElement或属性文本组成的列表
"""
@ -451,7 +450,7 @@ class ChromiumElement(DrissionElement):
return make_session_ele(self, loc_or_str, single=False)
def _ele(self, loc_or_str, timeout=None, single=True, relative=False):
"""返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个 \n
"""返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间
:param single: True则返回第一个False则返回全部
@ -460,7 +459,7 @@ class ChromiumElement(DrissionElement):
return find_in_chromium_ele(self, loc_or_str, single, timeout, relative=relative)
def style(self, style, pseudo_ele=''):
"""返回元素样式属性值,可获取伪元素属性值 \n
"""返回元素样式属性值,可获取伪元素属性值
:param style: 样式属性名称
:param pseudo_ele: 伪元素名称如有
:return: 样式属性的值
@ -500,7 +499,7 @@ class ChromiumElement(DrissionElement):
return data
def save(self, path=None, rename=None):
"""保存图片或其它有src属性的元素的资源 \n
"""保存图片或其它有src属性的元素的资源
:param path: 文件保存路径为None时保存到当前文件夹
:param rename: 文件名称为None时从资源url获取
:return: None
@ -518,7 +517,7 @@ class ChromiumElement(DrissionElement):
f.write(data)
def get_screenshot(self, path=None, as_bytes=None):
"""对当前元素截图 \n
"""对当前元素截图
:param path: 完整路径后缀可选 'jpg','jpeg','png','webp'
:param as_bytes: 是否已字节形式返回图片可选 'jpg','jpeg','png','webp'生效时path参数无效
:return: 图片完整路径或字节文本
@ -539,7 +538,7 @@ class ChromiumElement(DrissionElement):
left_top=left_top, right_bottom=right_bottom)
def input(self, vals, clear=True):
"""输入文本或组合键也可用于输入文件路径到input元素文件间用\n间隔) \n
"""输入文本或组合键也可用于输入文件路径到input元素文件间用\n间隔)
:param vals: 文本值或按键组合
:param clear: 输入前是否清空文本框
:return: None
@ -581,7 +580,7 @@ class ChromiumElement(DrissionElement):
self.page.run_cdp('DOM.setFileInputFiles', files=files, nodeId=self._node_id, not_change=True)
def clear(self, by_js=False):
"""清空元素文本 \n
"""清空元素文本
:param by_js: 是否用js方式清空
:return: None
"""
@ -592,8 +591,8 @@ class ChromiumElement(DrissionElement):
self.input(('\ue009', 'a', '\ue017'), clear=False)
def click(self, by_js=None, retry=False, timeout=.2, wait_loading=0):
"""点击元素 \n
如果遇到遮挡会重新尝试点击直到超时若都失败就改用js点击 \n
"""点击元素
如果遇到遮挡会重新尝试点击直到超时若都失败就改用js点击
:param by_js: 是否用js点击为True时直接用js点击为False时重试失败也不会改用js
:param retry: 遇到其它元素遮挡时是否重试
:param timeout: 尝试点击的超时时间不指定则使用父页面的超时时间retry为True时才生效
@ -643,7 +642,7 @@ class ChromiumElement(DrissionElement):
return False
def click_at(self, offset_x=None, offset_y=None, button='left'):
"""带偏移量点击本元素相对于左上角坐标。不传入x或y值时点击元素左上角可接受点击的点 \n
"""带偏移量点击本元素相对于左上角坐标。不传入x或y值时点击元素左上角可接受点击的点
:param offset_x: 相对元素左上角坐标的x轴偏移量
:param offset_y: 相对元素左上角坐标的y轴偏移量
:param button: 左键还是右键
@ -660,7 +659,7 @@ class ChromiumElement(DrissionElement):
self._click(x, y, 'right')
def r_click_at(self, offset_x=None, offset_y=None):
"""带偏移量右键单击本元素相对于左上角坐标。不传入x或y值时点击元素中点 \n
"""带偏移量右键单击本元素相对于左上角坐标。不传入x或y值时点击元素中点
:param offset_x: 相对元素左上角坐标的x轴偏移量
:param offset_y: 相对元素左上角坐标的y轴偏移量
:return: None
@ -674,7 +673,7 @@ class ChromiumElement(DrissionElement):
self._click(x, y, 'middle')
def _click(self, client_x, client_y, button='left'):
"""实施点击 \n
"""实施点击
:param client_x: 视口中的x坐标
:param client_y: 视口中的y坐标
:param button: 'left' 'right'
@ -686,7 +685,7 @@ class ChromiumElement(DrissionElement):
self.page.driver.Input.dispatchMouseEvent(type='mouseReleased', x=client_x, y=client_y, button=button)
def hover(self, offset_x=None, offset_y=None):
"""鼠标悬停可接受偏移量偏移量相对于元素左上角坐标。不传入x或y值时悬停在元素中点 \n
"""鼠标悬停可接受偏移量偏移量相对于元素左上角坐标。不传入x或y值时悬停在元素中点
:param offset_x: 相对元素左上角坐标的x轴偏移量
:param offset_y: 相对元素左上角坐标的y轴偏移量
:return: None
@ -696,7 +695,7 @@ class ChromiumElement(DrissionElement):
self.page.driver.Input.dispatchMouseEvent(type='mouseMoved', x=x, y=y)
def drag(self, offset_x=0, offset_y=0, speed=40, shake=True):
"""拖拽当前元素到相对位置 \n
"""拖拽当前元素到相对位置
:param offset_x: x变化值
:param offset_y: y变化值
:param speed: 拖动的速度传入0即瞬间到达
@ -709,7 +708,7 @@ class ChromiumElement(DrissionElement):
self.drag_to((offset_x, offset_y), speed, shake)
def drag_to(self, ele_or_loc, speed=40, shake=True):
"""拖拽当前元素,目标为另一个元素或坐标元组 \n
"""拖拽当前元素,目标为另一个元素或坐标元组
:param ele_or_loc: 另一个元素或坐标元组坐标为元素中点的坐标
:param speed: 拖动的速度传入0即瞬间到达
:param shake: 是否随机抖动
@ -747,7 +746,7 @@ class ChromiumElement(DrissionElement):
actions.release()
def _get_obj_id(self, node_id=None, backend_id=None):
"""根据传入node id获取js中的object id \n
"""根据传入node id获取js中的object id
:param node_id: cdp中的node id
:param backend_id: backend id
:return: js中的object id
@ -758,7 +757,7 @@ class ChromiumElement(DrissionElement):
return self.page.run_cdp('DOM.resolveNode', backendNodeId=backend_id, not_change=True)['object']['objectId']
def _get_node_id(self, obj_id=None, backend_id=None):
"""根据传入object id获取cdp中的node id \n
"""根据传入object id获取cdp中的node id
:param obj_id: js中的object id
:param backend_id: backend id
:return: cdp中的node id
@ -816,7 +815,7 @@ class ChromiumElement(DrissionElement):
return f':root{t}' if mode == 'css' else t
def _get_client_rect(self, quad):
"""按照类型返回窗口坐标 \n
"""按照类型返回窗口坐标
:param quad: 方框类型margin border padding
:return: 四个角坐标大小为0时返回None
"""
@ -857,8 +856,8 @@ class ChromiumShadowRootElement(BaseElement):
return f'<ShadowRootElement in {self.parent_ele} >'
def __call__(self, loc_or_str, timeout=None):
"""在内部查找元素 \n
ele2 = ele1('@id=ele_id') \n
"""在内部查找元素
ele2 = ele1('@id=ele_id')
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 超时时间
:return: DriverElement对象或属性文本
@ -910,7 +909,7 @@ class ChromiumShadowRootElement(BaseElement):
return self.run_js('return this.innerHTML;')
def run_js(self, script, as_expr=False, *args):
"""运行javascript代码 \n
"""运行javascript代码
:param script: js文本
:param as_expr: 是否作为表达式运行为True时args无效
:param args: 参数按顺序在js文本中对应argument[0]argument[1]...
@ -919,7 +918,7 @@ class ChromiumShadowRootElement(BaseElement):
return run_js(self, script, as_expr, self.page.timeouts.script, args)
def run_async_js(self, script, as_expr=False, *args):
"""以异步方式执行js代码 \n
"""以异步方式执行js代码
:param script: js文本
:param as_expr: 是否作为表达式运行为True时args无效
:param args: 参数按顺序在js文本中对应argument[0]argument[1]...
@ -929,7 +928,7 @@ class ChromiumShadowRootElement(BaseElement):
Thread(target=run_js, args=(self, script, as_expr, self.page.timeouts.script, args)).start()
def parent(self, level_or_loc=1):
"""返回上面某一级父元素,可指定层数或用查询语法定位 \n
"""返回上面某一级父元素,可指定层数或用查询语法定位
:param level_or_loc: 第几级父元素或定位符
:return: ChromiumElement对象
"""
@ -950,7 +949,7 @@ class ChromiumShadowRootElement(BaseElement):
return self.parent_ele._ele(loc, timeout=0, relative=True)
def next(self, filter_loc='', index=1):
"""返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个 \n
"""返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选元素的查询语法
:param index: 第几个查询结果元素
:return: ChromiumElement对象
@ -959,7 +958,7 @@ class ChromiumShadowRootElement(BaseElement):
return nodes[index - 1] if nodes else None
def before(self, filter_loc='', index=1):
"""返回前面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个 \n
"""返回前面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选元素的查询语法
:param index: 前面第几个查询结果元素
:return: 本元素前面的某个元素或节点
@ -968,7 +967,7 @@ class ChromiumShadowRootElement(BaseElement):
return nodes[index - 1] if nodes else None
def after(self, filter_loc='', index=1):
"""返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个 \n
"""返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选元素的查询语法
:param index: 后面第几个查询结果元素
:return: 本元素后面的某个元素或节点
@ -977,7 +976,7 @@ class ChromiumShadowRootElement(BaseElement):
return nodes[index - 1] if nodes else None
def nexts(self, filter_loc=''):
"""返回后面所有兄弟元素或节点组成的列表 \n
"""返回后面所有兄弟元素或节点组成的列表
:param filter_loc: 用于筛选元素的查询语法
:return: ChromiumElement对象组成的列表
"""
@ -990,7 +989,7 @@ class ChromiumShadowRootElement(BaseElement):
return self.parent_ele._ele(xpath, timeout=0.1, single=False, relative=True)
def befores(self, filter_loc=''):
"""返回后面全部兄弟元素或节点组成的列表,可用查询语法筛选 \n
"""返回后面全部兄弟元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选元素的查询语法
:return: 本元素前面的元素或节点组成的列表
"""
@ -1003,7 +1002,7 @@ class ChromiumShadowRootElement(BaseElement):
return self.parent_ele._ele(xpath, timeout=0.1, single=False, relative=True)
def afters(self, filter_loc=''):
"""返回前面全部兄弟元素或节点组成的列表,可用查询语法筛选 \n
"""返回前面全部兄弟元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选元素的查询语法
:return: 本元素后面的元素或节点组成的列表
"""
@ -1013,7 +1012,7 @@ class ChromiumShadowRootElement(BaseElement):
return eles1 + self.parent_ele._ele(xpath, timeout=0.1, single=False, relative=True)
def ele(self, loc_or_str, timeout=None):
"""返回当前元素下级符合条件的第一个元素 \n
"""返回当前元素下级符合条件的第一个元素
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:return: ChromiumElement对象
@ -1021,7 +1020,7 @@ class ChromiumShadowRootElement(BaseElement):
return self._ele(loc_or_str, timeout)
def eles(self, loc_or_str, timeout=None):
"""返回当前元素下级所有符合条件的子元素 \n
"""返回当前元素下级所有符合条件的子元素
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:return: ChromiumElement对象组成的列表
@ -1029,21 +1028,21 @@ class ChromiumShadowRootElement(BaseElement):
return self._ele(loc_or_str, timeout=timeout, single=False)
def s_ele(self, loc_or_str=None):
"""查找第一个符合条件的元素以SessionElement形式返回处理复杂页面时效率很高 \n
"""查找第一个符合条件的元素以SessionElement形式返回处理复杂页面时效率很高
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:return: SessionElement对象或属性文本
"""
return make_session_ele(self, loc_or_str)
def s_eles(self, loc_or_str):
"""查找所有符合条件的元素以SessionElement列表形式返回处理复杂页面时效率很高 \n
"""查找所有符合条件的元素以SessionElement列表形式返回处理复杂页面时效率很高
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:return: SessionElement对象
"""
return make_session_ele(self, loc_or_str, single=False)
def _ele(self, loc_or_str, timeout=None, single=True, relative=False):
"""返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个 \n
"""返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间
:param single: True则返回第一个False则返回全部

View File

@ -34,6 +34,7 @@ class ChromiumPage(ChromiumBase):
:return: None
"""
# 接管或启动浏览器
self._chromium_init()
if addr_driver_opts is None or isinstance(addr_driver_opts, (ChromiumOptions, DriverOptions)):
self._driver_options = addr_driver_opts or ChromiumOptions() # 从ini文件读取
self.address = self._driver_options.debugger_address
@ -62,9 +63,9 @@ class ChromiumPage(ChromiumBase):
else:
raise TypeError('只能接收ChromiumDriver或ChromiumOptions类型参数。')
self._init_page(tab_id)
self._set_options()
self._set_chromium_options()
self._init_page(tab_id)
self._get_document()
self._first_run = False
@ -75,11 +76,9 @@ class ChromiumPage(ChromiumBase):
script=self._driver_options.timeouts['script'],
implicit=self._driver_options.timeouts['implicit'])
self._page_load_strategy = self._driver_options.page_load_strategy
self.download_set.save_path(self._download_path)
def _set_chromium_options(self):
"""设置浏览器专有的配置"""
self._main_tab = self.tab_id
self._alert = Alert()
self._window_setter = None
@ -91,6 +90,13 @@ class ChromiumPage(ChromiumBase):
super()._init_page(tab_id)
self._tab_obj.Page.javascriptDialogOpening = self._on_alert_open
self._tab_obj.Page.javascriptDialogClosed = self._on_alert_close
self._main_tab = self.tab_id
try:
self.run_cdp('Browser.setDownloadBehavior', behavior='allow',
downloadPath=self._driver_options.download_path, not_change=True)
except:
self.run_cdp('Page.setDownloadBehavior', behavior='allow',
downloadPath=self._driver_options.download_path, not_change=True)
@property
def tabs_count(self):
@ -368,7 +374,7 @@ class ChromiumDownloadSetter(DownloadSetter):
"""用于设置下载参数的类"""
def save_path(self, path):
"""设置下载路径 \n
"""设置下载路径
:param path: 下载路径
:return: None
"""

View File

@ -16,7 +16,7 @@ from .configs.driver_options import DriverOptions
class ChromiumPage(ChromiumBase):
def __init__(self,
addr_driver_opts: Union[str, ChromiumDriver, DriverOptions] = None,
addr_driver_opts: Union[str, ChromiumOptions, DriverOptions] = None,
tab_id: str = None,
timeout: float = None):
self._driver_options: [ChromiumDriver, DriverOptions] = ...
@ -51,9 +51,6 @@ class ChromiumPage(ChromiumBase):
@property
def set_window(self) -> WindowSetter: ...
@property
def download_list(self) -> list: ...
@property
def download_set(self) -> ChromiumDownloadSetter: ...

View File

@ -27,6 +27,7 @@ def show_settings(ini_path=None):
def set_paths(driver_path=None,
chrome_path=None,
browser_path=None,
local_port=None,
debugger_address=None,
@ -35,8 +36,9 @@ def set_paths(driver_path=None,
cache_path=None,
ini_path=None,
check_version=False):
"""快捷的路径设置函数 \n
"""快捷的路径设置函数
:param driver_path: chromedriver.exe路径
:param chrome_path: 浏览器可执行文件路径
:param browser_path: 浏览器可执行文件路径
:param local_port: 本地端口号
:param debugger_address: 调试浏览器地址127.0.0.1:9222
@ -55,6 +57,9 @@ def set_paths(driver_path=None,
if driver_path is not None:
om.set_item('paths', 'chromedriver_path', format_path(driver_path))
if chrome_path is not None:
om.set_item('chrome_options', 'binary_location', format_path(browser_path))
if browser_path is not None:
om.set_item('chrome_options', 'binary_location', format_path(browser_path))
@ -80,7 +85,7 @@ def set_paths(driver_path=None,
def set_argument(arg, value=None, ini_path=None):
"""设置浏览器配置argument属性 \n
"""设置浏览器配置argument属性
:param arg: 属性名
:param value: 属性值有值的属性传入值没有的传入None
:param ini_path: 要修改的ini文件路径
@ -92,7 +97,7 @@ def set_argument(arg, value=None, ini_path=None):
def set_headless(on_off=True, ini_path=None):
"""设置是否隐藏浏览器界面 \n
"""设置是否隐藏浏览器界面
:param on_off: 开或关
:param ini_path: 要修改的ini文件路径
:return: None
@ -102,7 +107,7 @@ def set_headless(on_off=True, ini_path=None):
def set_no_imgs(on_off=True, ini_path=None):
"""设置是否禁止加载图片 \n
"""设置是否禁止加载图片
:param on_off: 开或关
:param ini_path: 要修改的ini文件路径
:return: None
@ -112,7 +117,7 @@ def set_no_imgs(on_off=True, ini_path=None):
def set_no_js(on_off=True, ini_path=None):
"""设置是否禁用js \n
"""设置是否禁用js
:param on_off: 开或关
:param ini_path: 要修改的ini文件路径
:return: None
@ -122,7 +127,7 @@ def set_no_js(on_off=True, ini_path=None):
def set_mute(on_off=True, ini_path=None):
"""设置是否静音 \n
"""设置是否静音
:param on_off: 开或关
:param ini_path: 要修改的ini文件路径
:return: None
@ -132,7 +137,7 @@ def set_mute(on_off=True, ini_path=None):
def set_user_agent(user_agent, ini_path=None):
"""设置user agent \n
"""设置user agent
:param user_agent: user agent文本
:param ini_path: 要修改的ini文件路径
:return: None
@ -141,7 +146,7 @@ def set_user_agent(user_agent, ini_path=None):
def set_proxy(proxy, ini_path=None):
"""设置代理 \n
"""设置代理
:param proxy: 代理网址和端口
:param ini_path: 要修改的ini文件路径
:return: None
@ -150,7 +155,7 @@ def set_proxy(proxy, ini_path=None):
def check_driver_version(driver_path=None, chrome_path=None):
"""检查传入的chrome和chromedriver是否匹配 \n
"""检查传入的chrome和chromedriver是否匹配
:param driver_path: chromedriver.exe路径
:param chrome_path: chrome.exe路径
:return: 是否匹配
@ -185,7 +190,7 @@ def get_match_driver(ini_path='default',
chrome_path=None,
show_msg=True,
check_version=True):
"""自动识别chrome版本并下载匹配的driver \n
"""自动识别chrome版本并下载匹配的driver
:param ini_path: 要读取和修改的ini文件路径
:param save_path: chromedriver保存路径
:param chrome_path: 指定chrome.exe位置
@ -237,7 +242,7 @@ def get_chrome_path(ini_path=None,
from_ini=True,
from_regedit=True,
from_system_path=True):
"""从ini文件或系统变量中获取chrome.exe的路径 \n
"""从ini文件或系统变量中获取chrome.exe的路径
:param ini_path: ini文件路径
:param show_msg: 是否打印信息
:param from_ini: 是否从ini文件获取
@ -310,7 +315,7 @@ def get_chrome_path(ini_path=None,
def _get_chrome_version(path: str) -> Union[str, None]:
"""根据文件路径获取版本号 \n
"""根据文件路径获取版本号
:param path: chrome.exe文件路径
:return: 版本号
"""
@ -327,7 +332,7 @@ def _get_chrome_version(path: str) -> Union[str, None]:
def _download_driver(version: str, save_path: str = None, show_msg: bool = True) -> Union[str, None]:
"""根据传入的版本号到镜像网站查找,下载最相近的 \n
"""根据传入的版本号到镜像网站查找,下载最相近的
:param version: 本地版本号
:return: 保存地址
"""

View File

@ -79,7 +79,7 @@ def get_ele_txt(e):
def format_html(text):
"""处理html编码字符 \n
"""处理html编码字符
:param text: html文本
:return: 格式化后的html文本
"""
@ -106,7 +106,7 @@ def location_in_viewport(page, loc_x, loc_y):
def offset_scroll(ele, offset_x, offset_y):
"""接收元素及偏移坐标,把坐标滚动到页面中间,返回该点在视口中的坐标 \n
"""接收元素及偏移坐标,把坐标滚动到页面中间,返回该点在视口中的坐标
有偏移量时以元素左上角坐标为基准没有时以_click_point为基准
:param ele: 元素对象
:param offset_x: 偏移量x
@ -164,7 +164,7 @@ def is_js_func(func):
def cookie_to_dict(cookie):
"""把Cookie对象转为dict格式 \n
"""把Cookie对象转为dict格式
:param cookie: Cookie对象
:return: cookie字典
"""
@ -199,7 +199,7 @@ def cookie_to_dict(cookie):
def cookies_to_tuple(cookies):
"""把cookies转为tuple格式 \n
"""把cookies转为tuple格式
:param cookies: cookies信息可为CookieJar, list, tuple, str, dict
:return: 返回tuple形式的cookies
"""

View File

@ -39,7 +39,7 @@ class MixPage(SessionPage, DriverPage, BasePage):
if self._mode == 'd':
try:
timeouts = self.drission.driver_options.timeouts
t = timeout if timeout is not None else timeouts['implicit']
t = timeout if isinstance(timeout, (int, float)) else timeouts['implicit']
self.set_timeouts(t, timeouts['pageLoad'], timeouts['script'])
except Exception:

View File

@ -38,24 +38,23 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
self._debug = False
self._debug_recorder = None
self.address = None
self._session = None
self._tab_obj = None
self._is_loading = False
self._driver_options = None
self._session_options = None
self._set_both_options(driver_or_options, session_or_options)
self._setting_tab_id = tab_id
self._response = None
self._download_kit = None
self._download_set = None
self._set_both_options(driver_or_options, session_or_options)
if self._mode == 'd':
self._to_d_mode()
t = timeout if timeout is not None else self.timeouts.implicit
t = timeout if isinstance(timeout, (int, float)) else self.timeouts.implicit
super(ChromiumBase, self).__init__(t) # 调用Base的__init__()
def _set_both_options(self, dr_opt, se_opt):
@ -64,10 +63,11 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
:param se_opt: SessionSessionOptions对象或配置信息为None则从ini读取为False用默认信息创建
:return: None
"""
# 浏览器配置
if isinstance(dr_opt, ChromiumDriver):
self._connect_browser(dr_opt)
self._has_driver = True
self._driver_options = None
# self._driver_options = None
dr_opt = False
else:
@ -81,12 +81,13 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
self._driver_options = dr_opt
else:
raise TypeError('driver_or_options参数只能接收ChromiumDriver, ChromiumOptionsOptions、None或False。')
raise TypeError('driver_or_options参数只能接收ChromiumDriver, ChromiumOptions、None或False。')
# Session配置
if isinstance(se_opt, Session):
self._session = se_opt
self._has_session = True
self._session_options = None
self._session_options = SessionOptions(read_file=False)
se_opt = False
else:
@ -102,13 +103,18 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
else:
raise TypeError('session_or_options参数只能接收Session, SessionOptions、None或False。')
# 通用配置
self._timeouts = Timeout(self)
self._page_load_strategy = self._driver_options.page_load_strategy
self._download_path = None
if se_opt is not False:
self.set_timeouts(implicit=self._session_options.timeout)
self._download_path = self._session_options.download_path
if dr_opt is not False:
t = self._driver_options.timeouts
self.set_timeouts(t['implicit'], t['pageLoad'], t['script'])
self._download_path = self._driver_options.download_path
def _set_options(self):
"""覆盖父类同名方法"""
@ -232,7 +238,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
return self._download_set
def get(self, url, show_errmsg=False, retry=None, interval=None, timeout=None, **kwargs):
"""跳转到一个url \n
"""跳转到一个url \n
:param url: 目标url
:param show_errmsg: 是否显示和抛出异常
:param retry: 重试次数
@ -249,7 +255,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
return super().get(url, show_errmsg, retry, interval, timeout, **kwargs)
def ele(self, loc_or_ele, timeout=None):
"""返回第一个符合条件的元素、属性或节点文本 \n
"""返回第一个符合条件的元素、属性或节点文本 \n
:param loc_or_ele: 元素的定位信息可以是元素对象loc元组或查询字符串
:param timeout: 查找元素超时时间默认与页面等待时间一致
:return: 元素对象或属性文本节点文本
@ -260,7 +266,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
return super(SessionPage, self).ele(loc_or_ele, timeout=timeout)
def eles(self, loc_or_str, timeout=None):
"""返回页面中所有符合条件的元素、属性或节点文本 \n
"""返回页面中所有符合条件的元素、属性或节点文本 \n
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间默认与页面等待时间一致
:return: 元素对象或属性文本组成的列表
@ -291,9 +297,9 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
return super(SessionPage, self).s_eles(loc_or_str)
def change_mode(self, mode=None, go=True, copy_cookies=True):
"""切换模式,接收's''d',除此以外的字符串会切换为 d 模式 \n
如copy_cookies为True切换时会把当前模式的cookies复制到目标模式 \n
切换后如果go是True调用相应的get函数使访问的页面同步 \n
"""切换模式,接收's''d',除此以外的字符串会切换为 d 模式 \n
如copy_cookies为True切换时会把当前模式的cookies复制到目标模式 \n
切换后如果go是True调用相应的get函数使访问的页面同步 \n
:param mode: 模式字符串
:param go: 是否跳转到原模式的url
:param copy_cookies: 是否复制cookies到目标模式
@ -333,7 +339,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
self.get(url)
def cookies_to_session(self, copy_user_agent=True):
"""把driver对象的cookies复制到session对象 \n
"""把driver对象的cookies复制到session对象 \n
:param copy_user_agent: 是否复制ua信息
:return: None
"""
@ -357,7 +363,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
self.set_cookies(cookies, set_driver=True)
def get_cookies(self, as_dict=False, all_domains=False):
"""返回cookies \n
"""返回cookies \n
:param as_dict: 是否以字典方式返回
:param all_domains: 是否返回所有域的cookies
:return: cookies信息
@ -368,6 +374,10 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
return self._get_driver_cookies(as_dict)
def _get_driver_cookies(self, as_dict=False):
"""获取浏览器cookies \n
:param as_dict: 以dict形式返回
:return: cookies信息
"""
cookies = self._tab_obj.Network.getCookies()['cookies']
if as_dict:
return {cookie['name']: cookie['value'] for cookie in cookies}
@ -399,7 +409,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
super().set_cookies(cookies)
def set_headers(self, headers: dict) -> None:
"""设置固定发送的headers \n
"""设置固定发送的headers \n
:param headers: dict格式的headers数据
:return: None
"""
@ -429,7 +439,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
# ----------------重写SessionPage的函数-----------------------
def post(self, url: str, data=None, show_errmsg=False, retry=None, interval=None, **kwargs):
"""用post方式跳转到url会切换到s模式 \n
"""用post方式跳转到url会切换到s模式 \n
:param url: 目标url
:param data: post方式时提交的数据
:param show_errmsg: 是否显示和抛出异常
@ -482,11 +492,10 @@ class WebPageDownloadSetter(ChromiumDownloadSetter):
self._behavior = 'allow'
def save_path(self, path):
"""设置下载路径 \n
"""设置下载路径
:param path: 下载路径
:return: None
"""
# todo: 设置时判断模式,初始设置
path = path or ''
path = Path(path).absolute()
path.mkdir(parents=True, exist_ok=True)
@ -506,14 +515,15 @@ class WebPageDownloadSetter(ChromiumDownloadSetter):
raise RuntimeError('浏览器未连接。')
self._page.driver.Page.downloadWillBegin = None
self._page.driver.Browser.downloadWillBegin = None
self._page.driver.Browser.setDownloadBehavior(behavior='allow')
self._page.driver.Browser.setDownloadBehavior(behavior='allow', downloadPath=self._page.download_path)
self._behavior = 'allow'
def use_DownloadKit(self):
"""设置使用DownloadKit下载文件"""
self._page.driver.Page.downloadWillBegin = self._download_by_DownloadKit
self._page.driver.Browser.downloadWillBegin = self._download_by_DownloadKit
self._page.driver.Browser.setDownloadBehavior(behavior='deny')
if self._page._has_driver:
self._page.driver.Page.downloadWillBegin = self._download_by_DownloadKit
self._page.driver.Browser.downloadWillBegin = self._download_by_DownloadKit
self._page.driver.Browser.setDownloadBehavior(behavior='deny')
self._behavior = 'deny'
def _download_by_DownloadKit(self, **kwargs):
@ -521,5 +531,5 @@ class WebPageDownloadSetter(ChromiumDownloadSetter):
self._page.run_cdp('Browser.cancelDownload', guid=gid, not_change=True)
url = kwargs['url']
name = kwargs['suggestedFilename']
print(f'开始下载:{url}')
print(f'下载:{url}')
self._page.download.add(url, goal_path=self._page.download_path, rename=name)

View File

@ -31,11 +31,13 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
self._mode: str = ...
self._has_driver: bool = ...
self._has_session: bool = ...
self.address: str = ...
self._session_options: Union[SessionOptions, None] = ...
self._driver_options: Union[DriverOptions, None] = ...
self._driver_options: Union[ChromiumOptions, DriverOptions, None] = ...
self._setting_tab_id: str = ...
self._download_kit: DownloadKit = ...
self._download_set: WebPageDownloadSetter = ...
self._download_path: str = ...
def __call__(self,
loc_or_str: Union[Tuple[str, str], str, ChromiumElement, SessionElement],