查找元素(二)

一、在结果列表中筛选

eles()nexts()等能够获取多个元素的方法,返回的列表可进行进一步筛选,以获取指定的元素。

示例1,筛选并返回元素列表:
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_foundTrue时抛出

示例如下:

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=' ')

解释:

  1. ele.filter.displayed(): 先过滤出所有显示的元素。
  2. ele.filter.text('图'): 再从中筛选出文本包含“图”的元素。
  3. 结果将是那些显示且包含“图”字的元素。

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)
posted @ 2019-08-29 21:18  酒剑仙*  阅读(858)  评论(0编辑  收藏  举报