查找元素(二)
一、在结果列表中筛选
eles()
、nexts()
等能够获取多个元素的方法,返回的列表可进行进一步筛选,以获取指定的元素。
from DrissionPage import ChromiumPage page = ChromiumPage() page.get('https://www.baidu.com') eles = page('#s-top-left').eles('t:a') # 获取左上角导航栏内所有<a>元素 for ele in eles.filter.displayed(): # 筛选出显示的元素列表并逐个打印文本 print(ele.text, end=' ')
输出:
新闻 hao123 地图 贴吧 视频 图片 网盘 文库 更多
示例2,筛选并返回第一个元素:
from DrissionPage import ChromiumPage page = ChromiumPage() page.get('https://www.baidu.com') eles = page('#s-top-left').eles('t:a') # 获取左上角导航栏内所有<a>元素 print(eles.filter_one.displayed().text) # 筛选出显示的元素并返回第一个
输出:
新闻
1.1.获取单个匹配元素
⑴.filter_one.displayed()
用于在元素列表中以是否显示为条件筛选元素(显示到页面的第一条结果),返回第一个结果。
参数:
参数名称 | 类型 | 默认值 | 说明 |
---|---|---|---|
equal |
bool |
True |
是否匹配显示的元素,False 匹配不显示的 |
返回值:
返回类型 | 说明 |
---|---|
ChromiumElement |
匹配成功返回元素对象 |
NoneElement |
失败返回NoneElement |
抛出ElementNotFoundError 异常 |
Settings.raise_when_ele_not_found 为True 时抛出 |
示例如下:
element = elements.filter_one.displayed()
⑵.filter_one.checked(equal=True)
作用: 以元素是否被选中为条件筛选。
参数:
- equal (bool): True 表示匹配被选中的元素,False 表示匹配不被选中的元素。
返回: 匹配成功返回 ChromiumElement,失败返回 NoneElement。
异常: 当 Settings.raise_when_ele_not_found 为 True 时抛出 ElementNotFoundError。
# 获取第一个被选中的元素: element = elements.filter_one.checked()
⑶.filter_one.selected(equal=True)
作用: 以 <select> 元素项目的选择状态为条件筛选。
参数:
- equal (bool): True 表示匹配被选择的元素,False 表示匹配不被选择的元素。
返回: 匹配成功返回 ChromiumElement,失败返回 NoneElement。
异常: 当 Settings.raise_when_ele_not_found 为 True 时抛出 ElementNotFoundError。
# 获取第一个选择的 <select> 元素项: element = elements.filter_one.selected()
⑷.filter_one.enabled(equal=True)
作用: 以元素是否可用为条件筛选。
参数:
- equal (bool): True 表示匹配可用的元素,False 表示匹配不可用的元素。
返回: 匹配成功返回 ChromiumElement,失败返回 NoneElement。
异常: 当 Settings.raise_when_ele_not_found 为 True 时抛出 ElementNotFoundError。
# 获取第一个可用的元素: element = elements.filter_one.enabled()
⑸.filter_one.clickable(equal=True)
作用: 以元素是否可点击为条件筛选。
参数:
- equal (bool): True 表示匹配可点击的元素,False 表示匹配不可点击的元素。
返回: 匹配成功返回 ChromiumElement,失败返回 NoneElement。
异常: 当 Settings.raise_when_ele_not_found 为 True 时抛出 ElementNotFoundError。
# 获取第一个可点击的元素: element = elements.filter_one.clickable()
⑹.filter_one.have_rect(equal=True)
作用: 以元素是否有大小为条件筛选。
参数:
- equal (bool): True 表示匹配有大小的元素,False 表示匹配没有大小的元素。
返回: 匹配成功返回 ChromiumElement,失败返回 NoneElement。
异常: 当 Settings.raise_when_ele_not_found 为 True 时抛出 ElementNotFoundError。
# 获取第一个有大小的元素: element = elements.filter_one.have_rect()
⑺.filter_one.style(name, value, equal=True)
作用: 以元素的 style 属性值为条件筛选。
参数:
- name (str): style 属性名称。
- value (str): 属性值。
- equal (bool): True 表示匹配指定的 style 值,False 表示匹配不指定的值。
返回: 匹配成功返回 ChromiumElement,失败返回 NoneElement。
异常: 当 Settings.raise_when_ele_not_found 为 True 时抛出 ElementNotFoundError。
# 获取第一个具有特定 style 属性值的元素: element = elements.filter_one.style(name='color', value='red')
⑻.filter_one.property(name, value, equal=True)
作用: 以元素的 property 属性值为条件筛选。
参数:
- name (str): property 属性名称。
- value (str): 属性值。
- equal (bool): True 表示匹配指定的 property 值,False 表示匹配不指定的值。
返回: 匹配成功返回 ChromiumElement,失败返回 NoneElement。
异常: 当 Settings.raise_when_ele_not_found 为 True 时抛出 ElementNotFoundError。
# 获取第一个具有特定 property 值的元素: element = elements.filter_one.property(name='disabled', value='true')
在浏览器自动化或网页测试中,property 通常指的是 HTML 元素的属性,但它与元素的 attribute 有一些区别。具体而言:property vs attribute
- attribute: 这是 HTML 元素的标准属性,如 id、class、href、src 等。attribute 是 HTML 元素的定义部分,存储在 HTML 文档中,并且可以通过 JavaScript 直接访问或修改。例如,<input type="text" value="example"> 中的 value 就是一个 attribute。
- property: 这是 JavaScript 对象模型中的属性,用于描述 HTML 元素在文档中的状态或行为。它们通常反映了元素的当前状态或动态值。例如,input 元素的 value 属性(属性名与 HTML 中的 attribute 相同)在 JavaScript 中称为 property,它可能会随着用户输入而改变。
假设你有一个 HTML 元素如下:
<input id="username" type="text" value="default" disabled>
在 JavaScript 中,这个元素有以下 attributes 和 properties:
Attributes:
- id: "username"
- type: "text"
- value: "default"
- disabled: "" (存在,表示禁用)
Properties:
- id: "username"
- type: "text"
- value: "default" (当前值可能会随着用户输入改变)
- disabled: true (表示元素当前是否被禁用)
使用 property 方法筛选元素
在使用 filter_one.property(name, value, equal=True) 方法时,你是通过 JavaScript 对象模型来筛选元素。举个例子:
element = elements.filter_one.property(name='disabled', value='true')
这个方法将筛选出 disabled 属性为 true 的元素,表示这些元素在当前状态下是禁用的。此时,property 指的是元素的动态状态而非静态 HTML 属性。
总结
- attribute: 静态定义的 HTML 元素属性。
- property: 动态描述 HTML 元素的 JavaScript 对象属性。
使用 filter_one.property 方法筛选元素时,你是在通过元素的动态状态或行为来进行筛选
⑼.filter_one.attr(name, value, equal=True)
作用: 以元素的 attribute 属性值为条件筛选。
参数:
- name (str): 属性名称。
- value (str): 属性值。
- equal (bool): True 表示匹配指定的 attribute 值,False 表示匹配不指定的值。
返回: 匹配成功返回 ChromiumElement,失败返回 NoneElement。
异常: 当 Settings.raise_when_ele_not_found 为 True 时抛出 ElementNotFoundError。\
# 获取第一个具有特定 attribute 值的元素: element = elements.filter_one.attr(name='data-id', value='123')
⑽.filter_one.text(text, fuzzy=True, contain=True)
作用: 以元素的文本内容为条件筛选。
参数:
- text (str): 用于匹配的文本。
- fuzzy (bool): True 表示模糊匹配,False 表示精确匹配。
- contain (bool): True 表示匹配包含指定文本的元素,False 表示不包含。
返回: 匹配成功返回 ChromiumElement,失败返回 NoneElement。
异常: 当 Settings.raise_when_ele_not_found 为 True 时抛出 ElementNotFoundError。
# 获取第一个文本包含“图”的元素: element = elements.filter_one.text(text='图') # 获取第二个文本包含“图”的元素: element = elements.filter_one(2).text('图')
1.2.获取全部匹配元素
静态元素列表只有filter.attr()
和filter.text()
方法。
⑴.filter.displayed()
作用: 过滤列表中是否显示的元素。
参数:
- equal (bool): 如果为True,匹配显示的元素;如果为False,匹配隐藏的元素。
返回类型: 返回一个新的过滤器对象,可以继续用于进一步过滤。
实例: 假设我们有一个网页上包含多个按钮,我们希望只选择那些当前可见的按钮:
# 过滤出所有当前显示的按钮
visible_buttons = all_buttons.filter.displayed(equal=True)
⑵.filter.checked()
作用: 过滤列表中是否被选中的元素。
参数:
- equal (bool): 如果为True,匹配选中的元素;如果为False,匹配未选中的元素。
返回类型: 返回一个新的过滤器对象,可以继续用于进一步过滤。
实例: 假设我们有一个复选框列表,我们只想找到所有已经被选中的复选框:
# 过滤出所有被选中的复选框 checked_checkboxes = all_checkboxes.filter.checked(equal=True)
⑶.filter.selected()
作用: 过滤列表中<select>标签下是否被选中的选项。
参数:
- equal (bool): 如果为True,匹配选中的选项;如果为False,匹配未选中的选项。
返回类型: 返回一个新的过滤器对象,可以继续用于进一步过滤。
实例: 假设我们有一个下拉菜单,我们只想找出所有被选中的选项:
# 过滤出所有被选中的下拉选项 selected_options = all_options.filter.selected(equal=True)
⑷.filter.enabled()
作用: 过滤列表中是否可用的元素。
参数:
- equal (bool): 如果为True,匹配可用的元素;如果为False,匹配禁用的元素。
返回类型: 返回一个新的过滤器对象,可以继续用于进一步过滤。
实例: 假设我们有一个按钮列表,我们只想选择那些可点击的按钮:
# 过滤出所有可用的按钮 enabled_buttons = all_buttons.filter.enabled(equal=True)
⑸.filter.clickable()
作用: 过滤列表中是否可点击的元素。
参数:
- equal (bool): 如果为True,匹配可点击的元素;如果为False,匹配不可点击的元素。
返回类型: 返回一个新的过滤器对象,可以继续用于进一步过滤。
实例: 假设我们有一个元素列表,我们需要找出所有可以点击的元素:
# 过滤出所有可点击的元素 clickable_elements = all_elements.filter.clickable(equal=True)
⑹.filter.have_rect()
作用: 过滤列表中是否具有尺寸的元素。
参数:
- equal (bool): 如果为True,匹配有尺寸的元素;如果为False,匹配无尺寸的元素。
返回类型: 返回一个新的过滤器对象,可以继续用于进一步过滤。
实例: 假设我们有一个元素列表,我们想找出所有实际显示在页面上的(具有尺寸的)元素:
# 过滤出所有具有尺寸的元素 sized_elements = all_elements.filter.have_rect(equal=True)
⑺.filter.style()
作用: 根据元素的样式值进行过滤。
参数:
- name (str): 样式属性名称。
- value (str): 样式属性值。
- equal (bool): 如果为True,匹配给定样式值;如果为False,匹配不含该样式值的元素。
返回类型: 返回一个新的过滤器对象,可以继续用于进一步过滤。
实例: 假设我们有一个元素列表,我们只想找出背景颜色为红色的元素:
# 过滤出背景颜色为红色的元素 red_background_elements = all_elements.filter.style(name='background-color', value='red', equal=True)
⑻.filter.property()
作用: 根据元素的属性值进行过滤。
参数:
- name (str): 属性名称。
- value (str): 属性值。
- equal (bool): 如果为True,匹配给定属性值;如果为False,匹配不含该属性值的元素。
返回类型: 返回一个新的过滤器对象,可以继续用于进一步过滤。
实例: 假设我们有一个元素列表,我们想找出所有具有特定 id
属性值的元素:
# 过滤出所有具有指定 id 属性的元素 elements_with_id = all_elements.filter.property(name='id', value='special-id', equal=True)
⑼.filter.attr()
作用: 根据元素的属性值进行过滤。
参数:
- name (str): 属性名称。
- value (str): 属性值。
- equal (bool): 如果为True,匹配给定属性值;如果为False,匹配不含该属性值的元素。
返回类型: 返回一个新的过滤器对象,可以继续用于进一步过滤。
实例: 与 .filter.property()
类似,假设我们想找出所有具有特定 class
属性的元素:
# 过滤出所有具有指定 class 属性的元素 elements_with_class = all_elements.filter.attr(name='class', value='highlight', equal=True)
⑽.filter.text()
作用: 根据元素的文本内容进行过滤。
参数:
- text (str): 需要匹配的文本。
- fuzzy (bool): 是否进行模糊匹配。
- contain (bool): 如果为True,匹配包含该文本的元素;如果为False,匹配不包含该文本的元素。
返回类型: 返回一个新的过滤器对象,可以继续用于进一步过滤。
实例: 假设我们要找出所有包含特定文本的元素(例如,包含“重要”字样的段落):
# 过滤出包含 "重要" 的文本的元素 important_text_elements = all_elements.filter.text(text='重要', fuzzy=False, contain=True)
1.3.多条件筛选
多条件筛选在自动化测试和网页操作中非常有用,它允许你根据多个条件来精确选择和操作元素。
- 与关系筛选: 通过链式操作依次应用多个条件,所有条件都需要满足。
- 或关系筛选: 使用
search()
或search_one()
方法,根据多个条件进行筛选,元素只需满足一个条件即可。 - 混合筛选: 将与关系和或关系结合使用,允许进行更复杂的筛选操作。
1.3.1.与关系筛选
作用: 与关系筛选是通过链式操作将多个条件串联起来,每个条件都会进一步缩小筛选结果。所有条件必须同时满足,才能选中元素。
示例: 假设我们要在一个网页导航栏中筛选出那些显示且包含“图”字的元素:
from DrissionPage import * page = ChromiumPage() page.get('https://www.baidu.com') # 选择导航栏中的所有链接 eles = page('#s-top-left').eles('t:a') # 筛选显示且包含“图”字的元素 for ele in eles.filter.displayed().text('图'): print(ele.text, end=' ')
解释:
ele.filter.displayed()
: 先过滤出所有显示的元素。ele.filter.text('图')
: 再从中筛选出文本包含“图”的元素。- 结果将是那些显示且包含“图”字的元素。
1.3.2.或关系筛选
作用: 或关系筛选允许你通过search()
和search_one()
方法来使用多个条件进行筛选。可以设定多个条件,元素只需满足其中一个条件即可被选中。
参数:
index
(int): 结果中的元素序号,1开始。displayed
(bool): 是否显示。checked
(bool): 是否被选中。selected
(bool): 是否被选择。enabled
(bool): 是否可用。clickable
(bool): 是否可点击。have_rect
(bool): 是否拥有大小。have_text
(bool): 是否含有文本。
示例: 筛选出含有文本或可用的超链接的herf属性
from DrissionPage import ChromiumPage page = ChromiumPage() page.get("https://www.baidu.com") # 筛选出含有文本或可用的超链接 all_a = page("#s-top-left").eles("tag:a").search(have_text=True, enabled=True) # 输出herf属性 for a in all_a: print(a.attr("href"))
输出:
http://news.baidu.com https://www.hao123.com?src=from_pc http://map.baidu.com http://tieba.baidu.com/ https://haokan.baidu.com/?sfrom=baidu-top http://image.baidu.com/ https://pan.baidu.com?from=1026962h https://wenku.baidu.com/?fr=bdpcindex https://chat.baidu.com/search?isShowHello=1&pd=csaitab&setype=csaitab&extParams=%7B%22enter_type%22%3A%22home_tab%22%7D http://www.baidu.com/more/ http://fanyi.baidu.com/ http://xueshu.baidu.com/ https://baike.baidu.com https://zhidao.baidu.com https://jiankang.baidu.com/widescreen/home http://e.baidu.com/ebaidu/home?refer=887 https://live.baidu.com/ http://music.taihe.com https://cp.baidu.com/?sa=bdindex http://www.baidu.com/more/
1.3.3.混合筛选
作用: 混合筛选允许将与关系和或关系结合使用,提供更复杂的筛选逻辑。
示例:访问指定的网页(百度首页)。获取所有显示且可用的链接元素
from DrissionPage import ChromiumPage page = ChromiumPage() page.get('https://www.baidu.com') # 获取所有按钮元素 links = page.eles('t:a').search(displayed=True).enabled() for link in links: print(link.attr("href"))
这段代码的整体作用是:
- 访问指定的网页(百度首页)。
- 获取所有显示且可用的链接元素。
- 输出每个符合条件的链接的
href
属性值,即每个链接的目标 URL。
1.4.获取筛选结果的属性集合
自动化测试和网页操作中,获取筛选结果的属性集合非常重要,可以帮助你提取和操作元素的各种信息。以下是关于 get.attrs()
、get.links()
和 get.texts()
方法的详细说明以及对应的代码示例:
1.4.1.get.attrs()
作用: 获取所有筛选结果中指定属性的值组成的列表。
参数:
name
(str): 属性名称(必须提供)。
返回类型:
List[str]
: 包含所有元素指定属性值的列表。
示例: 假设我们要从页面上的所有链接中提取它们的 href
属性值:
from DrissionPage import ChromiumPage page = ChromiumPage() page.get('https://www.baidu.com') eles = page('#s-top-left').eles('t:a') print(eles.get.attrs(name="href")) # 获取所有a标签href属性的值
输出:
['http://news.baidu.com', 'https://www.hao123.com?src=from_pc', 'http://map.baidu.com', 'http://tieba.baidu.com/', 'https://haokan.baidu.com/?sfrom=baidu-top', 'http://image.baidu.com/', 'https://pan.baidu.com?from=1026962h', 'https://wenku.baidu.com/?fr=bdpcindex', 'https://chat.baidu.com/search?isShowHello=1&pd=csaitab&setype=csaitab&extParams=%7B%22enter_type%22%3A%22home_tab%22%7D', 'http://www.baidu.com/more/', 'http://fanyi.baidu.com/', 'http://xueshu.baidu.com/', 'https://baike.baidu.com', 'https://zhidao.baidu.com', 'https://jiankang.baidu.com/widescreen/home', 'http://e.baidu.com/ebaidu/home?refer=887', 'https://live.baidu.com/', 'http://music.taihe.com', 'https://cp.baidu.com/?sa=bdindex', 'http://www.baidu.com/more/']
解释:
get.attrs(name='href')
: 获取这些链接的href
属性值。
1.4.2.get.links()
作用: 获取所有筛选结果中链接文本的值组成的列表。
参数: 无
返回类型:
List[str]
: 包含所有元素链接文本的列表。
示例: 假设我们要获取页面中所有链接的文本内容:
from DrissionPage import ChromiumPage page = ChromiumPage() page.get('https://www.baidu.com') eles = page('#s-top-left').eles('t:a') # 获取所有筛选结果中链接文本的值组成的列表。 print(eles.get.links())
输出:
['http://news.baidu.com', 'https://www.hao123.com?src=from_pc', 'http://map.baidu.com', 'http://tieba.baidu.com/', 'https://haokan.baidu.com/?sfrom=baidu-top', 'http://image.baidu.com/', 'https://pan.baidu.com?from=1026962h', 'https://wenku.baidu.com/?fr=bdpcindex', 'https://chat.baidu.com/search?isShowHello=1&pd=csaitab&setype=csaitab&extParams=%7B%22enter_type%22%3A%22home_tab%22%7D', 'http://www.baidu.com/more/', 'http://fanyi.baidu.com/', 'http://xueshu.baidu.com/', 'https://baike.baidu.com', 'https://zhidao.baidu.com', 'https://jiankang.baidu.com/widescreen/home', 'http://e.baidu.com/ebaidu/home?refer=887', 'https://live.baidu.com/', 'http://music.taihe.com', 'https://cp.baidu.com/?sa=bdindex', 'http://www.baidu.com/more/']
解释:
get.links()
: 获取这些链接的文本内容。
1.4.3.get.texts()
作用: 获取所有筛选结果中元素文本内容组成的列表。
参数: 无
返回类型:
List[str]
: 包含所有元素文本内容的列表。
示例: 假设我们要从页面中获取超链接的文本内容:
from DrissionPage import ChromiumPage page = ChromiumPage() page.get('https://www.baidu.com') eles = page('#s-top-left').eles('t:a') # 获取所有元素的文本 print(eles.get.texts())
输出:
['新闻', 'hao123', '地图', '贴吧', '视频', '图片', '网盘', '文库', 'AI助手', '更多', '翻译', '学术', '百科', '知道', '健康', '营销推广', '直播', '音乐', '橙篇', '查看全部百度产品 >']
解释:
get.texts()
: 获取这些按钮的文本内容。
二、简化写法
为进一步精简代码,定位语法都可以用简化形式来表示,使语句更短,链式操作时更清晰。
2.1.定位符语法简化
- 定位语法都有其简化形式
- 页面和元素对象都实现了
__call__()
方法,所以page.ele('****')
可简化为page('****')
- 查找方法都支持链式操作
示例:
# 查找tag为div的元素 ele = tab.ele('tag:div') # 原写法 ele = tab('t:div') # 简化写法 # 用xpath查找元素 ele = tab.ele('xpath://****') # 原写法 ele = tab('x://****') # 简化写法 # 查找text为'something'的元素 ele = tab.ele('text=something') # 原写法 ele = tab('tx=something') # 简化写法
简化写法对应列表
原写法 | 简化写法 | 说明 |
---|---|---|
@id |
# |
表示 id 属性,简化写法只在语句最前面且单独使用时生效 |
@class |
. |
表示 class 属性,简化写法只在语句最前面且单独使用时生效 |
text |
tx |
按文本匹配 |
@text() |
@tx() |
按文本查找,与 @ 或 @@ 配合使用时 |
tag |
t |
按标签类型匹配 |
@tag() |
@t() |
按元素名查找,与 @ 或 @@ 配合使用时 |
xpath |
x |
用 xpath 方式查找元素 |
css |
c |
用 css selector 方式查找元素 |
2.2.shadow root 简化
一般获取元素的 shadow root 元素,用ele.shadow_root
属性。
由于此属性经常用于大量链式操作,名字太长影响可读性,因此可简化为ele.sr
示例:
txt = ele.sr('t:div').text
2.3.相对定位参数简化
相对定位时,有时需要获取当前元素后某个元素,而不关心该元素是什么类型,一般是这样写:ele.next(index=2)
。但有一种简化的写法,可以直接写作ele.next(2)
。当第一个参数filter_loc
接收数字时,会自动将其视作序号,替代index
参数。因此书写可以稍微精简一些。示例:
ele2 = ele1.parent(2) ele2 = ele1.next(2)('tx=****') ele2 = ele1.before(2)