DrissionPage/docs/8_MixPage/5_element_operation.md
2023-02-03 00:03:36 +08:00

519 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

d 模式下的`DriverElement`对象可以对浏览器相应元素进行控制。
# ✔️ 元素操作方法
## 📍 `click()`
此方法用于点击元素。可以选择是否用 js 方式点击,可以在点击失败时自动重试。默认情况下,使用 selenium 原生的点击方法,如果重试超过限定时间,自动改用 js 方式点击。可通过`by_js`参数设置点击方式。
此设计除了可保证点击成功,还可以用于检测页面上的遮罩层是否消失。遮罩层经常出现在 js 方式翻页的时候,它出现的时候会阻碍 selenium
的原生点击,所以可以通过对其下面的元素不断重试点击,来判断遮罩层是否存在。当然,这个方法是否可行要看具体网页设计。
而如果直接使用 js 进行点击,则可无视任何遮挡,只要元素在 DOM 内,就能点击得到,这样可以根据须要灵活地对元素进行操作。
!> 注意:<br>使用 js 方式点击时,是不会进行重试的。
**参数:**
- `by_js`:是否用 js 方式点击,为`None`时先用 selenium 原生方法点击,重试失败超时后改为用 js 点击;为`True`时直接用 js 点击;为`False`时即使重试超时也不会改用 js。
- `timeout`:点击失败重试超时时间,为`None`时使用父页面`timeout`设置。
**返回:**`bool`,表示是否点击成功。
```python
# 点击一个元素,重试超时根据所在页面元素而定,都失败就改用 js 点击
ele.click()
# 点击一个元素,重试 5 秒,都失败也不改用 js 点击
ele.click(by_js=False, timeout=5)
# 假设遮罩层出现ele 是遮罩层下方的元素
ele.click(timeout = 10) # 不断重试点击,直到遮罩层消失,或到达 10 秒
ele.click(by_js=True) # 无视遮罩层,直接用 js 点击下方元素
```
## 📍 `click_at()`
此方法用于带偏移量点击元素,偏移量相对于元素左上角坐标。不传入`x``y`值时点击元素中点。可选择是否用 js 方式点击,但不会进行重试。
可用于点击一些奇怪的东西,比如用伪元素表示的控件。
点击的目标不一定在元素上,可以传入负值,或大于元素大小的值,点击元素附近的区域。向右和向下为正值,向左和向上为负值。
**参数:**
- `x`:相对元素左上角坐标的 x 轴偏移量
- `y`:相对元素左上角坐标的 y 轴偏移量
- `by_js`:是否用 js 点击
**返回:**`None`
```python
# 点击元素右上方 50*50 的位置
ele.click_at(50, -50)
# 点击元素上中部x 相对左上角向右偏移50y 保持在元素中点
ele.click_at(x=50)
# 点击元素中点,和 click() 相似,但没有重试功能
ele.click_at()
```
## 📍 `r_click()`
此方法实现右键单击元素。
**参数:**
**返回:**`None`
```python
ele.r_click()
```
## 📍 `r_click_at()`
此方法用于带偏移量右键点击元素,用法和`click_at()`相似,但没有`by_js`参数。
**参数:**
- `x`相对元素左上角坐标的x轴偏移量
- `y`相对元素左上角坐标的y轴偏移量
**返回:** `None`
```python
# 点击距离元素左上角 50*50 的位置(位于元素内部)
ele.r_click_at(50, 50)
```
## 📍 `input()`
此方法用于向元素输入文本或组合键,也可用于输入文件路径到`input`元素(文件间用`\n`间隔)。可选择输入前是否清空元素。
insure 参数为 `True` 时可自动确保输入正确。该功能是为了应对 selenium 原生输入在某些i情况下会失效的问题。但只能用于 input 元素且 `type``text` 的情况。 接收组合键的时候可接收
selenium 的 `Keys` 对象的值。组合键要放在一个 `tuple` 中传入。
!> **注意:** <br>`insure``True` 时不能用于接收组合键。
?> **Tips:** <br>- 有些文本框可以接收回车代替点击按钮,可以直接在文本末尾加上`'\n'`<br>- 非传入`tuple`时,会自动把非`str`转换为`str`
**参数:**
- `vals`:文本值或按键组合
- `clear`:输入前是否清空文本框
- `insure`:是否确保输入正确,不能用于输入组合键
- `timeout`:尝试输入的超时时间,不指定则使用父页面的超时时间,只在 `insure_input` 参数为 `True` 时生效
**返回:**`bool`类型,表示是否成功输入。`insure``False` 时始终返回 `True`
```python
# 输入文本
ele.input('Hello world!')
# 输入文本并回车
ele.input('Hello world!\n')
# 输入组合键
from selenium.webdriver import Keys
ele.input((Keys.CONTROL, 'a'), insure=False)
# 向上传文本控件输入文本路径(传入多个路径)
ele.input('D:\\test1.txt\nD:\\test2.txt')
```
## 📍 `clear()`
此方法用于清空元素文本,可使用确保清空的方式,若元素是不可编辑的,返回`None`
**参数:**
- `insure`:是否确保清空。为`True`则用`input()`确保值变成`''`,为`False`则用 selenium 元素`clear()`方法
**返回:**`bool`,是否清空成功,不能清空的元素返回`None`
```python
ele.clear()
```
## 📍 `run_script()`
此方法用于对元素执行 js 代码,代码中用`arguments[0]`表示自己。
**参数:**
- `script`js 文本
- `*args`:传入 js 的参数
**返回:** js 执行的结果
```python
# 用执行 js 的方式点击元素
ele.run_script('arguments[0].click()')
```
## 📍 `wait_ele()`
此方法用于等待当前元素的某个下级元素到达某种状态。
调用此方法返回一个`ElementWaiter`对象,调用该对象方法实现各种方式的等待。
**参数:**
- `loc_or_ele`:要等待的元素,可以是元素或定位符
- `timeout`:等待超时时间,默认使用页面超时时间
**方法:**
| 方法 | 参数说明 | 功能 |
|:---------:|:----:|:------------:|
| display() | 无 | 等待元素从 DOM 显示 |
| hidden() | 无 | 等待元素从 DOM 隐藏 |
| delete() | 无 | 等待元素从 DOM 删除 |
这些方法返回布尔值,代表是否等待成功。
```python
# 等待 id 为 div1 的元素显示,超时使用页面设置
ele.wait_ele('#div1').display()
# 等待 id 为 div1 的元素被删除(使用 loc 元组设置超时3秒
ele.wait_ele((By.ID, 'div1'), 3).delete()
# 等待已获取到的元素被隐藏
ele2 = ele1.ele('#div1')
ele1.wait_ele(ele2).hidden()
```
## 📍 `screenshot()`
此方法用于对元素进行截图。
如果是图片元素,会自动等待加载结束才截图。
此方法能自动获取能够使用的文件名,避免重名覆盖原有文件。并返回保存路径。
保存格式为 png也可以返回图片的二进制文本。
**参数:**
- `path`:图片保持路径
- `filename`:图片文件名,不传入时以元素`tag`标签命名
- `as_bytes`是否已字节形式返回图片为True时上面两个参数失效
**返回:** 图片完整路径或字节文本
```python
path = ele.screenshot(r'D:\tmp', 'img1') # 保存到路径文件名为img1.png
bytes = ele.screenshot(as_bytes=True) # 返回截图二进制文本
```
## 📍 `set_prop()`
此方法用于设置元素`property`属性。
**参数:**
- `prop` 属性名
- `value` 属性值
**返回:**`bool`,是否设置成功
```python
ele.set_prop('value', 'Hello world!')
```
## 📍 `set_attr()`
此方法用于设置元素`attribute`属性。
**参数:**
- `attr`:属性名
- `value`:属性值
**返回:**`bool`,是否设置成功
```python
ele.set_attr('href', 'http://www.gitee.com')
```
## 📍 `remove_attr()`
此方法用于删除元素`attribute`属性。
**参数:**
- `attr`:属性名
**返回:**`bool`,是否删除成功
```python
ele.remove_attr('href')
```
## 📍 `submit()`
此方法用于提交表单,若元素不在表单内,返回`None`,否则返回`True`
**参数:**
**返回:**`True``None`
```python
ele.submit()
```
## 📍 `drag()`
此方法用于拖拽元素到相对于当前的一个新位置,可以设置速度,可以选择是否随机抖动。
**参数:**
- `x`x 变化值
- `y`y 变化值
- `speed`:拖动的速度,传入 0 即瞬间到达
- `shake`:是否随机抖动
**返回:**`None`
```python
# 拖动当前元素到距离 50*50 的位置,速度为 100不随机抖动
ele.drag(50, 50, 100, False)
```
## 📍 `drag_to()`
此方法用于拖拽元素到另一个元素上或一个坐标上。
**参数:**
- `ele_or_loc` 另一个元素或坐标元组,接收元素时坐标是元素中点的坐标。可接收 selenium 的`WebElement`或本库的`DriverElement`
- `speed` 拖动的速度,传入 0 即瞬间到达
- `shake` 是否随机抖动
**返回:**`None`
```python
# 把 ele1 拖拽到 ele2 上
ele1 = page.ele('#div1')
ele2 = page.ele('#div2')
ele1.drag_to(ele2)
# 把 ele1 拖拽到网页 50, 50 的位置
ele1.drag_to((50, 50))
```
## 📍 `scroll`
此属性用于以某种方式滚动元素中的滚动条。
调用此属性返回一个`Scroll`对象,调用该对象方法实现各种方式的滚动。
| 方法 | 参数说明 | 功能 |
|:-----------------:|:------:|:----------------:|
| to_top() | 无 | 滚动到顶端,水平位置不变 |
| to_bottom() | 无 | 滚动到底端,水平位置不变 |
| to_half() | 无 | 滚动到垂直中间位置,水平位置不变 |
| to_rightmost() | 无 | 滚动到最右边,垂直位置不变 |
| to_leftmost() | 无 | 滚动到最左边,垂直位置不变 |
| to_location(x, y) | 滚动条坐标值 | 滚动到指定位置 |
| up(pixel) | 滚动的像素 | 向上滚动若干像素,水平位置不变 |
| down(pixel) | 滚动的像素 | 向下滚动若干像素,水平位置不变 |
| right(pixel) | 滚动的像素 | 向左滚动若干像素,垂直位置不变 |
| left(pixel) | 滚动的像素 | 向右滚动若干像素,垂直位置不变 |
```python
# 滚动到底部
ele.scroll.to_bottom()
# 滚动到最右边
ele.scroll.to_rightmost()
# 向下滚动 200 像素
ele.scroll.down(200)
# 滚动到指定位置
ele.scroll.to_location(100, 300)
```
## 📍 `hover()`
此方法用于模拟鼠标悬停在元素上,可接受偏移量,偏移量相对于元素左上角坐标。不传入`x``y`值时悬停在元素中点。`x``y`值可接受负值。
**参数:**
- `x`:相对元素左上角坐标的 x 轴偏移量
- `y`:相对元素左上角坐标的 y 轴偏移量
**返回:**`None`
```python
# 悬停在元素右上方 50*50 的位置
ele.hover(50, -50)
# 悬停在元素上中部x 相对左上角向右偏移50y 保持在元素中点
ele.hover(x=50)
# 悬停在元素中点
ele.hover()
```
# ✔️ `Select`类
`select`元素的操作较为复杂,因此专门做了一个类用于处理它。每个`DriverElement`都有`select`属性,如果是`select`元素,该属性是一个`Select`类,否则该属性为`False`
`select`元素要操作列表时,实际上是对这个`Select`对象进行操作。
```python
ele.select
```
?> **Tips:** <br>网页操作中经常遇到动态变化的表单,这时需要等待列表项加载。`Select`类内置等待功能,默认为页面等待时间。
## 📍 属性
### 📎 `is_multi`
该属性表示当前`select`元素是否多选列表。
```python
ele.select.is_multi
```
### 📎 `options`
该属性以列表形式返回当前`select`元素下所有列表项元素对象,这些对象是`DriverElement`
```python
options = ele.select.options
```
### 📎 `selected_option`
该属性返回第一个被选中的元素对象。
```python
option_ele = ele.select.selected_option
```
### 📎 `selected_options`
该属性以列表形式返回第所有被选中的元素对象。如果是单选列表,返回一个列表
```python
options = ele.select.select.selected_options
```
## 📍 方法
### 📎 `select()`
该方法用于选定下拉列表中子元素。
接收`int`类型时根据序号选择,接收`str`类型时根据文本选择。
接收`list``tuple`时同时选择多个项,多项可序号和文本混排。只能在多选列表使用。
Select 类的`__call__()`方法直接调用这个方法,因此可以直接`ele.select()`来替代这个方法。写法更直观。
**参数:**
- `text_or_index`:根据文本或序号择选项,若允许多选,传入`list``tuple`可多选
- `timeout`:等待列表项出现的时间
**返回:** 是否选择成功
```python
# 根据文本选择下拉列表项等待1秒
ele.select('text', timeout=1)
# 选择第一个下拉列表项
ele.select(0)
# 选择多个文本项
ele.select(('text1', 'text2'))
# 选择多个序号
ele.select((0, 2))
# 文本和序号混合选择
ele.select(('text1', 2))
```
### 📎 `select_by_value()`
**参数:**
- `value``value`属性值,若允许多选,传入`list``tuple`可多选
- `timeout`:等待列表项出现的时间
**返回:** 是否选择成功
此方法用于根据`value`值选择项。当元素是多选列表时,可以接受`list``tuple`,同时选择多个项,可和序号混排。
```python
# 根据 value 值选择列表项
ele.select.select_by_value('value1')
# 根据 value 值选择多个项
ele.select.select_by_value(('value1', 2))
```
### 📎 `deselect()`
此方法用于取消选定下拉列表中子元素。当元素是多选列表时,可以接受`list``tuple`,同时取消选择多个项。
**参数:**
- `text_or_index`:根据文本、值选或序号择选项,若允许多选,传入`list``tuple`可多选
- `timeout`:等待列表项出现的时间
**返回:** 是否取消选择成功
```python
# 根据文本取消选择下拉列表项
ele.select.deselect('text')
# 取消选择第一项
ele.select.deselect(0)
# 取消选择多个文本项
ele.select.deselect(('text1', 'text2'))
# 取消选择多个序号
ele.select.deselect((0, 1))
# 文本和序号混合取消选择
ele.select.deselect(('text1', 2))
```
### 📎 `deselect_by_value()`
此方法用于根据`value`值取消选择项。当元素是多选列表时,可以接受`list``tuple`,同时取消选择多个项,可和序号混排。
**参数:**
- `value``value`属性值,若允许多选,传入`list``tuple`可取消多项
- `timeout`:等待列表项出现的时间
**返回:** 是否取消选择成功
```python
# 根据 value 值取消选择列表项
ele.select.deselect_by_value('value1')
# 根据 value 值取消选择多个项
ele.select.deselect_by_value(('value1', 2))
```
## 📍 多项列表独有功能
### 📎 `clear()`
此方法用于清空多选列表选项。
**参数:**
**返回:**`None`
```python
ele.select.clear()
```
### 📎 `invert()`
此方法用于反选多选列表选项。
**参数:**
**返回:**`None`
```python
ele.select.invert()
```