鸽了好久的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("小凯老师")

 

本文转载自白月黑羽,稍作精简修改。

 


已有的事,后必再有;

已行的事,后必再行。

日光之下,并无新事。 

——《圣经·传道书》