1、CSS表达式
1、根据tag名获取元素
elements= wd.find_elements(By.CSS_SELECTOR,'div')
等价于:elements = wd.find_elements(By.TAG_NAME,'div')
2、根据id属性获取元素:#id
element = wd.find_element(By.CSS_SELECTOR,'#kw')
等价于:element = wd.find_element(By_ID,'kw')
3、通过classname获取:.classname
elements = wd.find_elements(By.CSS_SELECTOR,'.plant')
等价于:elements = wd.find_elements(By.CLASS-NAME,'plant')
4、选择直接子元素和后代元素
什么是直接子元素?
<div id='container'>
<div id='layer1'>
<div id='inner11'>
<span>内层11</span>
</div>
<div id='inner12'>
<span>内层12</span>
</div>
</div>
<div id='layer2'>
<div id='inner21'>
<span>内层21</span>
</div>
</div>
</div>
如上述代码,id为container的div直接包含id为layer1和layer2的div,则id为layer1和layer2的div就是container的直接子元素。同理,inner11和inner12是layer1的直接子元素,inner21是layer2的直接子元素。
如果 元素2
是 元素1
的 直接子元素,则CSS Selector选择子元素的语法为:
元素1 > 元素2
元素1 > 元素2 > 元素3 > 元素4 # 支持多级
什么是后代元素
inner11和inner12和inner21是container的后代子元素。
如果 元素2
是 元素1
的 后代子元素,则CSS Selector选择子元素的语法为:
元素1 元素2
元素1 元素2 元素3 元素4 # 支持多级
注意:直接子元素也属于后代子元素。
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.implicitly_wait(10)
wd.get("https://www.byhy.net/_files/stock1.html")
# 查询classname为search-result元素的所有属性为id的直接子元素
elements = wd.find_elements(By.CSS_SELECTOR,'.search-result > [id]')
for element in elements:
print(element.text)
print("-------------------------------------------------")
# 查询classname为search-result元素的所有属性为class的直接子元素
elements_2 = wd.find_elements(By.CSS_SELECTOR,'.search-result > [class]')
for element_2 in elements_2:
print(element_2.text)
5、根据属性选择
css 选择器支持通过任何属性来选择元素,语法是用一个方括号[]
。
<a href="http://www.miitbeian.gov.cn">苏ICP备88885574号</a>
# 根据属性选择元素
element = wd.find_element(By.CSS_SELECTOR, '[href="http://www.miitbeian.gov.cn"]')
div[class='SKnet']
表示 选择所有标签名为div,且class属性值为SKnet的元素。属性值用单引号,双引号都可以。
[href]
,表示选择所有具有属性名为href的元素,不管它们的值是什么。
a[href*="miitbeian"]
, 表示要选择a节点,里面的href属性包含了 miitbeian 字符串。
a[href^="http"]
,表示要选择a节点,里面的href属性以 http 开头 。
a[href$="gov.cn"]
,要选择a节点,里面的href属性以 gov.cn 结尾 。
如果一个元素具有多个属性
<div class="misc" ctype="gun">沙漠之鹰</div>
CSS 选择器可以指定选择的元素要同时具有多个属性的限制,像这样 div[class=misc][ctype=gun]
6、选择语法联合使用
<div id='bottom'>
<div class='footer1'>
<span class='copyright'>版权</span>
<span class='date'>发布日期:2018-03-03</span>
</div>
<div class='footer2'>
<span>备案号
<a href="http://www.miitbeian.gov.cn">苏ICP备88885574号</a>
</span>
</div>
</div>
.footer1 > .copyright # 选择一个class属性值为copyright 的节点(不限类型),并且要求其必须是class属性值为footer1的节点的子节点
div.footer1 > span.copyright # 选择一个class属性值为copyright的span节点,并且要求其必须是class属性值为footer1的div节点的子节点
7、组选择
.plant , .animal
:同时选择所有class 为 plant 和 class 为 animal 的元素
8、按次序选择子节点
<body>
<div id='t1'>
<h3> 唐诗 </h3>
<span>李白</span>
<p>静夜思</p>
<span>杜甫</span>
<p>春夜喜雨</p>
</div>
<div id='t2'>
<h3> 宋词 </h3>
<span>苏轼</span>
<p>赤壁怀古</p>
<p>明月几时有</p>
<p>江城子·乙卯正月二十日夜记梦</p>
<p>蝶恋花·春景</p>
<span>辛弃疾</span>
<p>京口北固亭怀古</p>
<p>青玉案·元夕</p>
<p>西江月·夜行黄沙道中</p>
</div>
</body>
- 父元素的第n个子节点:
nth-child
span:nth-child(2)
:选择第2个子元素,并且是span类型:nth-child(2)
:选择所有位置为第2个的所有元素,不管是什么类型
- 父元素的倒数第n个子节点:
nth-last-child
p:nth-last-child(1)
:选择第倒数第1个子元素,并且是p元素
- 父元素的第几个某类型的子节点:
nth-of-type
span:nth-of-type(1)
:第1个span类型 的子元素
- 父元素的倒数第几个某类型的子节点:
nth-last-of-type
- 奇数节点和偶数节点
p:nth-child(even)
:偶数节点p:nth-child(odd)
:奇数节点
2、frame切换
frame元素
frame是一个十分特殊的元素,在html语法中,frame 元素或者iframe元素的内部会包含一个被嵌入的另一份html文档。如果我们要操作被嵌入的html 文档中的元素,就必须
切换操作范围
到被嵌入的文档中。
wd.switch_to.frame("frame1") #切换到frame
wd.switch_to.default_content() # 切换回最外部的HTML中
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.implicitly_wait(10)
wd.get("https://cdn2.byhy.net/files/selenium/sample2.html")
# 获取所有的plant种类
wd.switch_to.frame("frame1") #切换到frame
plant_elements = wd.find_elements(By.CLASS_NAME,'plant')
for plant_element in plant_elements:
print(plant_element.text)
# 获取外部按钮
wd.switch_to.default_content() # 切换回最外部的HTML中
button_element = wd.find_element(By.CSS_SELECTOR,'#outerbutton')
button_element.click()
pass
3、切换到新的窗口
用途:打开一个新的窗口,在新的窗口中进行自动化测试。
语法:wd.switch_to.window(handle)
,handle可以看作是想要打开窗口的id。
怎么判断打开的是自己想要的窗口?
通过WebDriver对象的window_handles 属性遍历所有窗口,然后通过目标窗口的某些属性判断是否是目标窗口。
如何返回原来的窗口?
进入新窗口操作完后,先保存该老窗口的oldhandle(
oldhandle= wd.current_window_handle
),后续通过wd.switch_to.window(oldhandle)
返回老窗口
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.implicitly_wait(10)
wd.get("https://cdn2.byhy.net/files/selenium/sample3.html")
element = wd.find_element(By.TAG_NAME,'a')
element.click()
for handle in wd.window_handles:
# 保存旧窗口的handle
old_handle = wd.current_window_handle
# 先切换到该窗口
wd.switch_to.window(handle)
# 判断目标窗口
if '必应' in wd.title:
break
print(wd.title)
# 回到旧窗口
wd.switch_to.window(old_handle)
print(wd.title)
pass
4、选择框
-
radio选择框——直接使用click()模拟用户点击即可
# radio选择框——直接使用click()模拟用户点击即可 radio_element = wd.find_element(By.CSS_SELECTOR,'#s_radio input[value="小雷老师"]') radio_element.click() print("当前选择的为:"+radio_element.get_attribute("value")) #获取元素属性
-
checkbox选择框——直接使用click()模拟用户点击即可
需要注意的是,要选中checkbox的一个选项,必须 先获取当前该复选框的状态
,如果该选项已经勾选了,就不能再点击。否则反而会取消选择。
实现思路为先把已经选中的选项全部点击一下,确保都是未选状态,然后再进行选择。
# checkbox选择框——直接使用click()模拟用户点击即可
# 先取消所有的点击状态
check_elements = wd.find_elements(By.CSS_SELECTOR,'#s_checkbox input[checked="checked"]')
for check_element in check_elements:
check_element.click()
check_element = wd.find_element(By.CSS_SELECTOR,'#s_checkbox input[value="小雷老师"]')
check_element.click()
print("当前选择的为:"+check_element.get_attribute("value"))
-
select框
<option value="foo">Bar</option>
-
select_by_value
:根据选项的value属性值
,选择元素s.select_by_value('foo')
-
select_by_index
:根据选项的次序
(从0开始),选择元素select_by_index(0)
-
select_by_visible_text
:根据选项的可见文本
,选择元素s.select_by_visible_text('Bar')
-
deselect_by_value
:根据选项的value属性值,去除
选中元素 -
deselect_by_index
:根据选项的次序,去除
选中元素 -
deselect_by_visible_text
:根据选项的可见文本,去除
选中元素 -
deselect_all
:去除
选中所有元素
# 导入Select类 from selenium.webdriver.support.ui import Select # select单选框 # 创建select对象 select_element = Select(wd.find_element(By.ID,'ss_single')) # 通过select对象选中目标 select_element.select_by_value("小雷老师") # select多选框 # 创建select对象 select_elements = Select(wd.find_element(By.ID,'ss_multi')) # 清除所有已选择 select_elements.deselect_all() # 多选 select_elements.select_by_value("小雷老师") select_elements.select_by_value("小江老师")
-
5、Xpath选择器
-
绝对路径选择
elements = driver.find_elements(By.XPATH, "/html/body/div")
-
相对路径选择
//div
:页面的所有 div元素//div//p
:所有的 div 元素里面的所有的p元素//div/p
:所有的 div 元素里面的直接子节点p//div/*
:所有div节点的所有直接子节点elements = driver.find_elements(By.XPATH, "//div//p")
-
根据属性选择
语法:
[@属性名='属性值']
- 根据id选择:
//*[@id='west']
- 根据class属性选择:
//select[@class='single_choice']
- 根据其他属性
- 要选择 style属性值 包含 color 字符串的 页面元素 ,可以这样
//*[contains(@style,'color')]
- 要选择 style属性值 以 color 字符串
开头
的 页面元素 ,可以这样//*[starts-with(@style,'color')]
- 根据id选择:
-
按次序选择
- 某类型第几个子元素:
//p[2]
:p类型第2个的子元素//div/p[2]
:选取父元素为div中的p类型第2个子元素//div/*[2]
:选择父元素为div的第2个子元素,不管是什么类型
- 某类型倒数第几个子元素
//p[last()]
:选取p类型倒数第1个子元素//p[last()-1]
:选取p类型倒数第2个子元素
- 某类型第几个子元素:
-
范围选择
//option[position()<=2]
:选取option类型第1到2个子元素//*[@class='multi_choice']/*[position()<=3]
:选择class属性为multi_choice的前3个子元素//*[@class='multi_choice']/*[position()>=last()-2]
:选择class属性为multi_choice的后3个子元素
-
组选择:css 组选择,表达式之间用逗号隔开xpath也有组选择,是用竖线隔开多个表达式。
//option | //h4
:选所有的option元素和所有的h4元素
-
选择父节点:某个元素的父节点用
/..
表示//*[@id='china']/..
:选择 id 为 china 的节点的父节点
-
兄弟节点选择:following-sibling::
//*[@class='single_choice']/following-sibling::*
:选择 class 为 single_choice 的元素的所有后续兄弟节点//*[@class='single_choice']/preceding-sibling::*[1]
:选择 class 为 single_choice 的元素的前面最靠近的兄弟节点