隐式等待是通过一定的时长等待页面所元素加载完成。哪果超出了设置的时长元素还没有被加载测抛
NoSuchElementException 异常。WebDriver 提供了 implicitly_wait()方法来实现隐式等待,默认设置为 0。它
的用法相对来说要简单的多。
baidu.py
#coding=utf-8
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
driver = webdriver.Firefox()
driver.implicitly_wait(10)
input_ = driver.find_element_by_id("kw22")
input_.send_keys('selenium')
driver.quit()
implicitly_wait()默认参数的单位为秒,本例中设置等待时长为 10 秒,首先这 10 秒并非一个固定的等
待时间,它并不影响脚本的执行速度。其次,它并不真对页面上的某一元素进行等待,当脚本执行到某个
元素定位时,如果元素可定位那么继续执行,如果元素定位不到,那么它将以轮询的方式不断的判断元素
是否被定位到,假设在第 6 秒钟定位到元素则继续执行。直接超出设置时长(10 秒)还没定位到元素则抛
出异常。
在上面的例子中,显然百度输入框的定位 id=kw22 是有误的,那么在超出 10 秒后将抛出异常。
Python Shell
>>> ================================ RESTART ================================
>>>
Traceback (most recent call last):
File "C:\Users\fnngj\Desktop\aaa.py", line 19, in <module>
bb = driver.find_element_by_id("kw22")
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py",
line 206, in find_element_by_id
return self.find_element(by=By.ID, value=id_)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py",
line 662, in find_element
{'using': by, 'value': value})['value']
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py",
line 173, in execute
self.error_handler.check_response(response)
File
"C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py",
line 166, in check_response
raise exception_class(message, screen, stacktrace)
NoSuchElementException: Message: Unable to locate element:
{"method":"id","selector":"kw22"}
sleep 休眠方法
有时间我们希望脚本执行到某一位置时做固定时间的休眠,尤其是在脚本调试的过程中。那么可以使用 sleep()方法,需要说明的是 sleep()由 Python 的 time 模块提供。
baidu.py
#coding=utf-8
from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
sleep(2)
driver.find_element_by_id("kw").send_keys("webdriver")
driver.find_element_by_id("su").click()
sleep(3)
driver.quit()
当执行到 sleep()方法时会固定的休眠所设置的时长,然后再继续执行。sleep()方法默认参数以秒为单
位,如果设置时长小于 1 秒,可以用小数点表示,如:sleep(0.5)
定位一组元素
在本章的第一节我们已经学习了 8 种定位方法,那 8 种定位方法是真对单元素定位的,WebDriver 还
提供了与之对应的 8 种定位方法用于定位一组元素。
find_elements_by_id()
find_elements_by_name()
find_elements_by_class_name()
find_elements_by_tag_name()
find_elements_by_link_text()
find_elements_by_partial_link_text()
find_elements_by_xpath()
find_elements_by_css_selector()
定位一组对象的方法与定位单个对象的方法类似,唯一的区别是在单词 element 后面多了一个 s 表示
复数。定位一组对象一般用于以下场景:
批量操作对象,比如将页面上所有的复选框都被勾选。
先获取一组对象,再在这组对象中过滤出需要具体定位的一些对象。比如定位出页面上所有的
checkbox,然后选择最后一个。
checkbox.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>Checkbox</title>
</head>
<body>
<h3>checkbox</h3>
<div class="well">
<form class="form-horizontal">
<div class="control-group">
<label class="control-label" for="c1">checkbox1</label>
<div class="controls">
<input type="checkbox" id="c1" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="c2">checkbox2</label>
<div class="controls">
<input type="checkbox" id="c2" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="c3">checkbox3</label>
<div class="controls">
<input type="checkbox" id="c3" />
</div>
</div>
</form>
</div>
</body>
</html>
这里手动创建一个 checkbox.html 的页面,通过浏览器打开,效果如图。
为了使页面更美观,在代码中添加了 bootstrap 在线样式的引用。下面就通过例子来操作页面上的这一
组复选框。
checkbox.py
#coding=utf-8
from selenium import webdriver
import os
driver = webdriver.Firefox()
driver.get(file_path)
# 选择页面上所有的 tag name 为 input 的元素
inputs = driver.find_elements_by_tag_name('input')
#然后从中过滤出 tpye 为 checkbox 的元素,单击勾选
for i in inputs:
if i.get_attribute('type') == 'checkbox':
i.click()
driver.quit()
前面在提到通过 tag name 的定位方式很难定位到单个元素,因为元素标签名重复的概率很高。那么在
定位一组元素时,这种方式就派上了用场。上面的例子中先通过 find_elements_by_tag_name()找到一组标
签名为 input 的元素。然后通过 for 循环进行遍历。在遍历的过程中通过 get_attribute()方法获取元素的 type
属性,判断是否为“chcckbox”,如果为“chcckbox”那么这个元素就是一个复选框。对其进行 click()勾
选操作。
在本例中,因为通过浏览器打开的是一个本地的 html 文件,所以需要用到 Python 的 os 模块,
path.abspath()方法用于获取当前路径下的文件。
除此之外,我们也可以使用 XPath 或 CSS 来判断属性值,从而进行点击操作。
checkbox.py
#coding=utf-8
from selenium import webdriver
import os
driver = webdriver.Firefox()
driver.get(file_path)
#通过 XPath 找到 type=checkbox 的元素
#checkboxes = driver.find_elements_by_xpath("//input[@type='checkbox']")
#通过 CSS 找到 type=checkbox 的元素
checkboxes = driver.find_elements_by_css_selector('input[type=checkbox]')
for checkbox in checkboxes:
checkbox.click()
# 打印当前页面上 type 为 checkbox 的个数
print len(checkboxes)
# 把页面上最后 1 个 checkbox 的勾给去掉
driver.find_elements_by_css_selector('input[type=checkbox]').pop().click()
driver.quit()
通过 XPath 或 CSS 来查找一组元素,少去判断步骤,因为它本身已经做了判断,只需要循环对每一
个元素进行 click()勾选即可。
除此之外例子中还用到了 Python 所提供的两个有趣的方法。len()可获取元素的个数,通过 print 打印
会得到一个 3 的结果。pop() 函数用于获取列表中的一个元素(默认为最后一个元素),并且返回该元素
的值。因为前的循环已经所有复选框都勾选上了,再对这一组元素执行 pop().lick() 其实是对后一个元素取
消勾选。如果只想勾选一组元素中的某一个呢。
pop()或 pop(-1) 默认获取一组元素中的最后一个。
pop(0) 默认获取一组元素中的第一个。
pop(1) 默认获取一组元素中的第二个。
……
这样就可以操作这一组元素中的元素了,只用数一数操作的元素是这一组中的第几个。