鸽了好久的selenium第二篇,磨磨蹭蹭到今天才发出来,其实一方面是最近拖延症比较严重,另一方面是最近开始学习前端的知识,对于网页元素、css样式和js代码,有了一些了解,再回过头来看selenium的选择方法理解更透彻了。
CSS表达式选择
上一篇在选择网页元素的时候是通过调用不同的python方法来对不同的网页元素进行选择,但在比较复杂的网页中,网页元素的属性会较为复杂,仅仅通过一种方法选择网页元素时容易出现多选或者漏选的情况。
而这时候就可以通过CSS表达式进行选择,CSS作为前端三大件之一,在网页设计中用来给特定元素添加自定义样式,因此在网页元素选择方面是极为强大的,而在python中调用也很简单。
普通选择
选择单个元素
find_element_by_css_selector(CSS表达式参数)
选择所有符合条件的元素
find_elements_by_css_selector(CSS表达式参数)
选择所有的tag名为div的元素
elements = wd.find_elements_by_css_selector('div')
根据id属性选择
element = wd.find_element_by_css_selector('#searchtext')
根据class属性
elements = wd.find_elements_by_css_selector('.animal')
直接子元素和后代元素
在网页中,经常会有元素嵌套的情况,在这样嵌套的时候,是一层层包裹起来的。
当B元素被A元素包裹时,B元素时A元素的后代元素。
当B元素只被A元素包裹时,中间没有其他层级时,B元素就是A元素的直接子元素。
综合以上定义,直接子元素时后代元素的特例。
这样在选择元素时可以更加精确。
在选择直接子元素时
elements = wd.find_elements_by_css_selector('元素1 > 元素2 > 元素3')
在选择后代元素时
elements = wd.find_elements_by_css_selector('元素1 元素2 元素3')
最终选择到的是元素3
其他属性选择
id、class等都是网页元素的属性,其他属性也可以用css选择其进行选择。
css 选择器支持通过任何属性来选择元素,语法是用一个方括号 [] 。
根据超链接href选择
element = wd.find_element_by_css_selector('[href="https://www.yumefx.com"]')
前面可以加上标签名的限制,比如 div[class=’search’] 表示 选择所有 标签名为div,且class属性值为search的元素。
根据属性选择,还可以不指定属性值,比如 [href] , 表示选择 所有 具有 属性名 为href 的元素,不管它们的值是什么。
CSS 还可以选择 属性值 包含 某个字符串 的元素
比如, 要选择a节点,里面的href属性包含了 miitbeian 字符串,就可以这样写
a[href*="yumefx"]
如果一个元素具有多个属性
<div class="weapon" ctype="gun">M4</div>
CSS 选择器 可以指定 选择的元素要 同时具有多个属性的限制,像这样
div[class=weapon][ctype=gun]
复杂使用
与网页的CSS样式用法一样,CSS选择器也可以联合使用
多维选择
elements = wd.find_elements_by_css_selector('.animal .cat')
多个选择
elements = wd.find_elements_by_css_selector('.dog , .cat')
按次序选择
父元素的第n个子节点使用 nth-child
span类型的第二个子元素这样写 span:nth-child(2)
如果不加节点类型限制,直接这样写 :nth-child(2)
,就是忽视类型,选择所有位置为第2个的元素
同理,倒数第n个子节点使用nth-last-child
第几个某类型的子节点使用 nth-of-type
倒数第几个某类型的子节点使用 nth-last-of-type
父元素的偶数节点,使用 nth-child(even)
父元素的奇数节点,使用 nth-child(odd)
父元素的某类型偶数节点,使用 nth-of-type(even)
父元素的某类型奇数节点,使用 nth-of-type(odd)
相邻兄弟选择使用+号表示,后续所有兄弟节点使用~表示
frame/窗口切换
有时要选择的元素在<iframe
包裹内,是无法直接选取到的, 在html语法中,frame 元素 或者iframe元素的内部 会包含一个 被嵌入的 另一份html文档。
当使用selenium打开一个网页时,操作范围只在当前网页,并不包含被嵌入的html网页的内容,因此需要切换操作范围。
使用 WebDriver 对象的 switch_to 属性,像这样
wd.switch_to.frame(frame_reference)
其中, frame_reference 可以是 frame 元素的属性 name、ID 或者frame 所对应的 WebElement 对象。
也可以根据frame的元素位置或者属性特性,使用find系列的方法,选择到该元素,得到对应的WebElement对象。
wd.switch_to.frame(wd.find_element_by_tag_name("iframe"))
然后就可以自由操作frame里面的元素了。
切换回原来的主html则可以使用
wd.switch_to.default_content()
切换窗口时,使用Webdriver对象的switch_to属性的 window方法,如下所示:
wd.switch_to.window(handle)
WebDriver对象有window_handles 属性,这是一个列表对象, 里面包括了当前浏览器里面所有的窗口句柄。
所谓句柄,可以想象成对应网页窗口的一个ID,通过 类似下面的代码获取。
for handle in wd.window_handles: # 先切换到该窗口 wd.switch_to.window(handle) # 得到该窗口的标题栏字符串,判断是不是我们要操作的那个窗口 if 'Bing' in wd.title: # 如果是,那么这时候WebDriver对象就是对应的该该窗口,正好,跳出循环, break # mainWindow变量保存当前窗口的句柄 mainWindow = wd.current_window_handle
选择框
radio框
radio框选择选项,直接用WebElement的click方法,模拟用户点击就可以了。
# 获取当前选中的元素 element = wd.find_element_by_css_selector( '#s_radio input[checked=checked]') print('当前选中的是: ' + element.get_attribute('value')) # 点选 小雷老师 wd.find_element_by_css_selector( '#s_radio input[value="小雷老师"]').click()
checkbox框
需要注意的是,要选中checkbox的一个选项,必须 先获取当前该复选框的状态 ,如果该选项已经勾选了,就不能再点击。否则反而会取消选择。
# 先把 已经选中的选项全部点击一下 elements = wd.find_elements_by_css_selector( '#s_checkbox input[checked="checked"]') for element in elements: element.click() # 再点击 小雷老师 wd.find_element_by_css_selector( "#s_checkbox input[value='小雷老师']").click()
select框
radio框及checkbox框都是input元素,只是里面的type不同而已。
select框 则是一个新的select标签,对于Select 选择框, Selenium 专门提供了一个 Select类 进行操作。
Select类 提供了以下方法
- select_by_value
根据选项的 value属性值 ,选择元素。
比如,下面的HTML
<option value="foo">Bar</option>
就可以根据 foo 这个值选择该选项,
s.select_by_value('foo')
- select_by_index
根据选项的 次序 (从0开始),选择元素
- select_by_visible_text
根据选项的 可见文本 ,选择元素。
比如,下面的HTML,
<option value="foo">Bar</option>
就可以根据 Bar 这个内容,选择该选项
s.select_by_visible_text('Bar')
- deselect_by_value
根据选项的value属性值, 去除 选中元素
- deselect_by_index
根据选项的次序,去除 选中元素
- deselect_by_visible_text
根据选项的可见文本,去除 选中元素
- deselect_all
去除 选中所有元素
Select单选框
对于 select单选框,操作比较简单:
不管原来选的是什么,直接用Select方法选择即可。
# 导入Select类 from selenium.webdriver.support.ui import Select # 创建Select对象 select = Select(wd.find_element_by_id("ss_single")) # 通过 Select 对象选中小雷老师 select.select_by_visible_text("小雷老师")
Select多选框
对于select多选框,要选中某几个选项,要注意去掉原来已经选中的选项。
# 导入Select类 from selenium.webdriver.support.ui import Select # 创建Select对象 select = Select(wd.find_element_by_id("ss_multi")) # 清除所有 已经选中 的选项 select.deselect_all() # 选择小雷老师 和 小凯老师 select.select_by_visible_text("小雷老师") select.select_by_visible_text("小凯老师")
本文转载自白月黑羽,稍作精简修改。
已有的事,后必再有;
已行的事,后必再行。
日光之下,并无新事。
——《圣经·传道书》
评论
613229 618431dude this just inspired a post of my own, thanks 799012
564520 729899I want going to comment as this posts a bit old now, but just wanted to say thanks. 440687