一、标签元素的定位和操作
1、元素的定位
•⼋种策略、两套⽅法(单/多)、⻓款和短款⽅法名⻛格
1.1 单元素定位 —— find_element
•单元素定位的特点
。单元素定位的⽅法的返回值是 WebElement 类型的,代表找到的⻚⾯上的标签元素对象。
。如果⻚⾯上没有匹配条件的元素,会因为没有找到元素⽽报错(NoSuchElementException)
。如果⻚⾯上有多个匹配条件的标签元素,只返回第1个标签元素
。尽量根据标签上的唯⼀特征进⾏定位
•单元素定位的⽅法
。dr.find_element_by_id("id属性值") —— 根据标签上的id属性
。dr.find_element_by_name("name属性值") —— 根据标签上的name属性
。dr.find_element_by_class_name("class属性值") —— 根据标签上的class属性
。dr.find_element_by_tag_name("标签名") —— 根据标签名
。dr.find_element_by_link_text("链接⽂本") —— 根据超链接标签的⽂本
。dr.find_element_by_partial_link_text("部分链接⽂本") —— 根据部分超链接⽂本
。dr.find_element_by_css_selector("CSS选择器表达式") —— 根据CSS选择器
。dr.find_element_by_xpath("XPATH表达式") —— 根据XPATH表达式
1.2 多元素定位(使⽤场景⽐单元素定位少得多)—— find_elements
•多元素定位的特点
。多元素定位的⽅法的返回值是 list 列表类型的,代表找到⻚⾯上的⼀组标签元素的容器,列表中每个元素的类型是 WebElement 。
。如果⻚⾯上没有匹配条件的元素,不会报错,只是列表的⻓度为0,列表为空 [] 。
•多元素定位的⽅法
。dr.find_elements_by_id("id属性值") —— 根据标签上的id属性
。dr.find_elements_by_name("name属性值") —— 根据标签上的name属性
。dr.find_elements_by_class_name("class属性值") —— 根据标签上的class属性
。dr.find_elements_by_tag_name("标签名") —— 根据标签名
。dr.find_elements_by_link_text("链接⽂本") —— 根据超链接标签的⽂本
。dr.find_elements_by_partial_link_text("部分链接⽂本") —— 根据部分超链接
⽂本
。dr.find_elements_by_css_selector("CSS选择器表达式") —— 根据CSS选择器
。dr.find_elements_by_xpath("XPATH表达式") —— 根据XPATH表达式
1.3 使⽤By类和短款⽅法名⻛格的元素定位⽅法
•在selenium4的版本开始,不推荐使⽤⻓款的⽅法名⻛格定位元素
•推荐使⽤By类(元素定位的策略类)结合短款的⽅法名⻛格定位元素
。By.ID 、 By.NAME 、 By.CLASS_NAME 、 By.TAG_NAME 、 By.LINK_TEXT
。By.PARTIAL_LINK_TEXT 、 By.CSS_SELECTOR 、 By.XPATH
。注意:By类是selenium定义的类,需要导⼊: from selenium.webdriver.common.byimport By
•短款⽅法名⻛格的元素定位⽅法
。dr.find_element(By.XXX, "值")
。dr.find_elements(By.XXX, "值")
2、元素的操作
2.1 对标签元素的理解
•⻚⾯上的标签元素,在selenium体系下,被封装定义成了 WebElement 类—— 标签元素类
•⻚⾯上的每⼀个标签元素都是 WebElement 类的对象实例
2.2 标签元素的常⽤操作
•标签元素.send_keys("⽂本") —— 向标签元素中输⼊⽂本内容
•标签元素.click() —— 单击标签元素
•标签元素.clear() —— 清空⽂本框中的⽂本
•标签元素.get_attribute("标签属性名") —— 获取标签上指定属性的值
•标签元素.text —— 获取标签元素的⽂本(双标签之间的⽂本)
二、PATH表达式
1. 对xpath表达式的理解
•selenium只是借助了xpath表达式来定位元素
•xpath最早是应⽤于XML⽂件中定位标签元素的⼀套表达式,使⽤路径⻛格的分隔符表示标签的层级。
。XML和HTML的区别
□XML(extensible markup language)的标签是编写者⾃定义的,HTML的标签是预定义好的。
□XML的标签不是为了让浏览器渲染的,也不是为了展示数据,⽽是传输、存储数据的。
□HTML的标签是为了让浏览器选择展示数据的。
。XML的实例⽂件代码
<company>
<name>成都中⼼</name>
<address>成都市锦江区东⼤街</address>
<classes>
<class id="c073434">
<name>169期</name>
<master>小明</master>
<open>2022-3-5</open>
</class>
<class id="c073430">
<name>170期</name>
<master>小红</master>
<open>2022-3-14</open>
</class>
</classes>
</company>
•完全可以将HTML看作⼀个XML的特定实例,让XPATH去定位HTML⽂件中的标签
2. xpath的路径
•xpath表达式的路径永远从整个⽂档的“根”(根标签之前)开始计算的
•xpath表达式必须要有节点路径
•xpath中的路径分隔符
。/ —— 进⼊到当前节点的下⼀级
。// —— 进⼊到当前节点的下任意多级
。.. —— 进⼊到当前节点的上⼀级
3. xpath的谓语(筛选条件)
•谓语:对满⾜路径节点的标签元素进⼀步筛选的条件,谓语不能单独作为xpath表达式,必须要有路径节点
•语法: /xxx[谓语] 、 //xxx[谓语]、//✲[谓语]
3.1 可以在谓语中使⽤标签属性
•语法: @属性名
//p[@class="zz"] 匹配任意节点下的p标签,但p标签上必须有class="zz"属性
3.2 可以在谓语中使⽤⼦标签在其⽗标签下的排⾏顺序(是从1开始计数的,不⽀持负数)
•语法: N
//p[2] 匹配任意节点下的p标签,但它必须是其⽗标签下的所有p标签中的第2个
3.3 可以在谓语中使⽤丰富的XPATH的内置函数
•last() —— 匹配最后⼀个⼦元素
•position() —— 返回⼦标签在其⽗标签下的排⾏顺序(是从1开始计数的)
•text() —— 获取标签元素的内部⽂本(开始标签跟结束标签之间的⽂本)
•contains(A, B) —— 匹配A包含B的的元素
//p[last()] 匹配任意节点下的p标签,但它必须是其⽗标签下的所有p标签中的最后1个
//p[position()=2] 匹配任意节点下的p标签,但它在其⽗标签下所有的p标签中的排⾏必须等于2
//p[position()!=1] 匹配任意节点下的p标签,但它在其⽗标签下所有的p标签中的排⾏必须不等于1
//a[text()='帮助'] 匹配任意节点下的a标签,但它的内部⽂本必须等于“帮助”
//a[contains(text(), 'Pow')] 匹配任意节点下的a标签,但它的内部⽂本必须包含“Pow”
3.4 可以使⽤丰富的运算符
•关系运算符 —— = != > >= < <=
•算术运算符 —— + - * div mod
•逻辑运算符 —— and or not()
4. xpath中的“轴”
•当我们很难直接定位到⽬标元素时,我们可以先定位到跟⽬标元素相近的相关元素,再以这个相关元素为轴,进⾏某种⽅向的偏移,偏移到⽬标元素。本质上轴就是⼀种偏移关系。
•具体的轴实例
。preceding-sibling:: —— 同级之前轴
。parent:: —— ⽗级(上⼀级)轴
。following-sibling:: —— 同级之后轴
。……
三、使⽤Select 类操作⻚⾯上的下拉选择框
1. 对Select类的理解
•Selenium定义了Select类,代表⻚⾯上的select标签元素(下拉选择框)。
•创建Select类对象实例,调⽤⽅法,来选中下拉框中的选项。
•在创建Select类的对象实例时,需要传⼊定位到的⻚⾯上的select标签元素对象。
2. 选中选项的三个⽅法
# 选中⽂本为“硕⼠”的选项
Select(dr.find_element(By.ID, "edu")).select_by_visible_text("硕⼠")
# 选中value为“xx”的选项
Select(dr.find_element(By.ID, "edu")).select_by_value("xx")
# 选中索引为3(第4个)的选项
Select(dr.find_element(By.NAME, "edu")).select_by_index(3)
四、调⽤ dr.switch_to.alert.xxx 来操作⻚⾯上的JS对话框
1. 使⽤场景
•当⻚⾯上弹出了JS对话框,因为它不是标签元素,所以⽆法定位。
2. ⼀个属性和三个⽅法
dr.switch_to.alert.text
dr.switch_to.alert.accept()
dr.switch_to.alert.dismiss()
dr.switch_to.alert.send_keys("⽂本")
五、调⽤dr.switch_to.frame(XX) 将驱动对象切换到指定框架内
1. 使⽤场景
•当要定位的元素在 frame 或 iframe 标签(这些就是框架标签)⾥,我们⽆法直接定位到框架内部的元素,因此需要先将驱动对象(dr)切换进⼊到指定的框架内部,再定位元素
2.将驱动对象切换到框架内部
•dr.switch_to.frame(框架特征)
•框架特征:
。可以传⼊框架标签的id或name属性(这跟元素定位⽆关,切换框架的特征,只能⽤id和name)
。可以传⼊框架标签的索引(在外部⻚⾯所有框架标签中的排⾏顺序,从0开始编号)
•注意点:
。firefox浏览器切换框架有bug,请使⽤Chrome浏览器。
3. 将驱动对象切换到外部⻚⾯
•dr.switch_to.default_content() —— 切换到最外部⻚⾯
•dr.switch_to.parent_frame() —— 切换到上⼀级⻚⾯
六、使⽤ ActionChains 完成⼀些特殊的⿏标操作
1. 代码的套路
from selenium.webdriver import ActionChains
ActionChains(驱动).操作1(元素).操作2(元素).操作N(元素).perform()
2. ⿏标操作的⽅法
•double_click(元素) —— 双击元素
•move_to_element(元素) —— 移动到元素上
•context_click(元素) —— 右键点击元素
•click_and_hold(元素) —— 点住元素不放
•release() —— 放开⿏标
•……
七、三种等待
1. 强制等待
•调⽤ sleep 函数,让程序休眠指定的时⻓
•sleep函数使⽤的场景最多,但有⼀个确定是必须事先确定⼀个固定的休眠时⻓。
2. 隐式等待(智能等待 —— 等待到元素出现就不等了)
•调⽤驱动对象的 implicitly_wait ⽅法,事先设定⼀个最⼤的等待时⻓(秒),调⽤这个⽅法的时候,程序不会暂停,这只是⼀个设置。
•影响的是使⽤该驱动对象在后续定位元素时,可能因为元素不存在,⽽等待元素的出现。
。如果元素出现了,就结束等待,直接返回这个元素。
。如果元素⼀直不出现,超过了实现设定的最⼤等待时⻓,程序会报错。
•隐式等待只需要设置⼀次,后续⽤该驱动对象定位元素的所有⽅法都会受影响。
dr.implicitly_wait(10)
3. 显式等待(智能等待—— 等待到元素出现就不等了)
•如果使⽤显式等待定位元素的⽅法,就不使⽤传统定位元素的⽅法(find_element)
•使⽤WebDriverWait类对象的until⽅法,等待元素的出现
•想等待哪个元素,才对哪个元素调⽤显式等待定位的⽅法
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.expected_conditions import
presence_of_element_located
element = WebDriverWait(dr, 10).until(presence_of_element_located((By.ID,"cont")))
print(element.text)