Selenium 是一个 Web 应用的自动化框架。
通过它,我们可以写出自动化程序,像人一样在浏览器里操作web界面。 比如点击界面按钮,在文本框中输入文字等操作。
一、准备工作
1.安装客户端库:pip install selenium
会出现运行超时的情况,无法成功安装
建议使用镜像下载,可以使用的有:
阿里云:http://mirrors.aliyun.com/pypi/simple/
清华:https://pypi.tuna.tsinghua.edu.cn/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
华中理工大学:http://pypi.hustunique.com/
山东理工大学:http://pypi.sdutlinux.org/
豆瓣:http://pypi.douban.com/simple/
例如利用清华的:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple selenium
2.安装浏览器驱动,建议使用谷歌浏览器
谷歌浏览器驱动下载地址:https://chromedriver.storage.googleapis.com/index.html
选择与使用的谷歌浏览器相对应的版本号进行下载
解压,可放在D盘根目录下
简单的测试例子:
打开百度的网页:
from selenium import webdriver
# 创建 WebDriver 对象,指明使用chrome浏览器驱动
wd=webdriver.Chrome(r'D:\chromedriver.exe')
# 调用WebDriver 对象的get方法 可以让浏览器打开指定网址
wd.get('https://www.baidu.com/')
运行结果:
二、选择元素的基本方法
1.根据 元素的id 属性选择元素
如果元素有id, 根据id选择元素是最简单高效的方式
根据id寻找元素,找到后返回WebElement类型的对象
调用这个对象的send_keys方法就可以在对应的元素中输入字符串;调用这个对象的click方法就可以点击该元素
# 创建 WebDriver 对象,指明使用chrome浏览器驱动
wd=webdriver.Chrome(r'D:\webdrivers\chromedriver.exe')
# 调用WebDriver 对象的get方法 可以让浏览器打开指定网址
wd.get('https://www.baidu.com/')
# 根据id寻找元素,找到后返回WebElement类型的对象,可以对其进行操作
element=wd.find_element_by_id('kw')
s1=unicode('哈利波特','utf-8')
element.send_keys(s1) # 调用这个对象的send_keys方法就可以在对应的元素中输入字符串
click=wd.find_element_by_id('su')
click.click() # 调用这个对象的click方法就可以点击该元素
2.根据 class属性 选择元素
根据class属性选择元素,找到符合条件的元素可能不止只有一个
用elements=wd.find_elements_by_class_name('XXX')
找到的符合条件的所有元素并放在一个列表中返回,若找不到,则返回空列表
用elements=wd.find_element_by_class_name('XXX')
只会返回找到的第一个元素,若找不到,抛出异常NoSuchElementException
PS:通过WebElement对象的 text属性 可以获取该元素 在网页中的文本内容,例如:print elements.text
3.根据tag名选择元素
与上面根据class属性选择元素类似
element=wd.find_elements_by_tag_name('span')
element=wd.find_element_by_tag_name('span')
4.通过WebElement对象选择元素
WebElement对象也可以调用 find_elements_by_xxx, find_element_by_xxx 之类的方法
WebDriver对象选择元素的范围是整个web页面, 而WebElement对象选择元素的范围是该元素的内部
PS:find_elements是查找符合某条件的一组元素,以列表的形式返回
# 通过WebElement对象选择元素
element=wd.find_element_by_id('container')
spans=element.find_elements_by_tag_name('span')
for span in spans:
print span.text
5.等待界面元素出现
在我们进行网页操作的时候,有的元素内容不是可以立即出现的,可能会等待一段时间
Selenium的Webdriver对象 有个方法叫 implicitly_wait(设置最大等待时间),当发现元素没有找到的时候, 并不立即抛出异常。而是周期性(每隔半秒钟)重新寻找该元素,直到该元素找到,或者超出指定最大等待时长,这时才抛出异常(如果是 find_elements 之类的方法,则是返回空列表)
加入如下代码:
wd.implicitly_wait(10) # 每隔半秒寻找一次,最长等待时间为10秒
则后续所有的 find_element 或者 find_elements 之类的方法调用都会采用上面的策略:如果找不到元素,每隔半秒钟再去界面上查看一次, 直到找到该元素,或者过了10秒最大时长(会超出异常或返回空列表)
简单小例子:在百度上搜索“哈利波特”,并返回搜索的第一条数据
# 创建 WebDriver 对象,指明使用chrome浏览器驱动
wd=webdriver.Chrome(r'D:\webdrivers\chromedriver.exe')
wd.implicitly_wait(10) # 设置最长等待时间,每隔半秒寻找一次,最长等待时间为10秒
# 调用WebDriver 对象的get方法 可以让浏览器打开指定网址
wd.get('https://www.baidu.com/')
element=wd.find_element_by_id('kw')
s1=unicode('哈利波特','utf-8')
element.send_keys(s1) # 输入哈利波特
click=wd.find_element_by_id('su')
click.click() # 点击百度一下
element01=wd.find_element_by_id('content_left')
results=element01.find_element_by_id('1')
print results.text # 打印指定元素
运行结果:
三、操纵元素的基本方法
1.点击元素
可使用 click方法,或者在输入的文本后面加’/’
2.输入框
可使用send_keys方法
PS:若需把输入框中已经有的内容清除掉,可使用clear方法,例如:element.clear() # 清除输入框已有的字符串
3.获取元素信息
# 获取元素的文本内容
print results.text
# 通过WebElement对象的get_attribute方法来获取元素的属性值
print (results.get_attribute('srcid')) # 获取元素属性srcid的值
# 获取整个元素对应的HTML文本内容
print results.get_attribute('outerHTML')
# 获取某个元素内部的HTML文本内容
print results.get_attribute('innerHTML')
# 获取输入框里面的文字
print element.get_attribute('value')
四、CSS Selector语法选择元素
1.根据 tag名、id、class选择元素
wd=webdriver.Chrome(r'D:\webdrivers\chromedriver.exe')
wd.implicitly_wait(10) # 设置最长等待时间,每隔半秒寻找一次,最长等待时间为10秒
# 调用WebDriver 对象的get方法 可以让浏览器打开指定网址
wd.get('http://cdn1.python3.vip/files/selenium/sample1.html')
element=wd.find_element_by_css_selector('div') # 根据tag标签
print element.text
element01=wd.find_element_by_css_selector('.animal') # 根据class属性,前面需要加.
print element01.text
element02=wd.find_element_by_css_selector('#searchtext') # 根据id寻找,前面需要加#
element02.send_keys('hello')
print element02.get_attribute('value')
wd.quit()
2.选择子元素和后代元素(起到了限制范围的作用)
从上图:
id 为 layer1 和 layer2 的两个div元素是id 为 container 的div元素的直接子元素,也是后代元素
id 为 inner11 和 inner12 的两个div元素是id 为 container 的div元素的后代元素
(1)如果元素2是元素1的直接子元素,CSS Selector选择子元素的语法是“元素1 > 元素2”
例如:elements=wd.find_elements_by_css_selector('#container > div')
可以是#container > #layer1
而不能是#container > layer1
(2)如果元素2是元素1的后代元素,CSS Selector选择子元素的语法是“元素1 元素2”(中间是一个或者多个空格隔开)
例如:elements=wd.find_elements_by_css_selector('#container span')
3.根据属性选择
element01=wd.find_elements_by_css_selector('[href="http://www.miitbeian.gov.cn"]')
for element in element01:
print element.text
4.验证CSS表达式
5.组选择
例如同时选择所有class为plant和class为animal的元素,css选择器可以使用逗号 ,称之为组选择
即:.plant,.animal
6.按次序选择子节点(重要)
(1)父元素的第n个子节点
(2)父元素的倒数第n个子节点
(3)父元素的第几个某类型的子节点
(4)父元素的倒数第几个某类型的子节点
(5)奇数节点和偶数节点
(6)兄弟节点选择
五、frame切换/窗口切换
1.切换到frame
在html语法中,frame元素或者iframe元素的内部会包含一个被嵌入的另一份html文档,如果我们要操作被嵌入的html文档中的元素,就必须 切换操作范围到被嵌入的文档中wd.switch_to.frame(frame_reference)
,frame_reference可以是frame元素的属性name或者ID
若要切换回原来的主html,则wd.switch_to.default_content()
PS:如果元素在iframe里,在窗口里找是找不到元素的,更是无法点击。所以,要切换到iframe里去找元素。
2.切换到新的窗口
在网页中打开一个新网址,进行操作,但是此时操作的对象仍为老窗口,自动化操作也是在老窗口进行
如果要切换到新窗口进行操作,可以使用Webdriver对象的switch_to属性的window方法wd.switch_to.window(handle)
link=wd.find_element_by_css_selector('[href="http://www.bing.com"]') # 找到要打开的网址
link.click() # 点击,打开新网址
print wd.title
mainWindow=wd.current_window_handle # 将老窗口先进行保存
for handle in wd.window_handles: # 依次获取所有窗口的句柄对象
wd.switch_to.window(handle) # 先切换到该窗口
s1=unicode('CSDN - 专业开发者社区','utf-8') # 想要切换到的窗口标题栏
if s1 in wd.title: # 得到该窗口的标题栏字符,与我们要切换的窗口进行对比
break # 如果是,则跳出循环,此时刚好wd对象就是对应的该窗口
print wd.title
wd.switch_to.window(mainWindow) # 切换到老窗口
六、选择框
1.radio框
radio框选择选项,直接用WebElement的click方法,模拟用户点击
# CSS表达式定位到需要点击的元素,直接用click()方法
wd.find_element_by_css_selector('#s_radio input[value="小雷老师"]').click()
2.checkbox框
checkbox框是选中checkbox的一个选项,必须先获取当前该复选框的状态 ,如果该选项已经勾选了,就不能再点击。否则反而会取消选择。所以我们需将已经选中的选项全部点击一下,确保都是未选状态,再找出需要点击的元素用click()
# 将已经选中的选项全部点击一下,确保都是未选状态,再找出需要点击的元素用click()
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() # 定位,点击
3.select框
(1)select单选框,直接用Select方法选择
# 导入Select类
from selenium.webdriver.support.ui import Select
# 创建Select对象
select=Select(wd.find_element_by_css_selector('#ss_single'))
# 通过Select对象选中小雷老师
select.select_by_visible_text("小雷老师")
(2)Select多选框
对于select多选框,要选中某几个选项,要注意去掉原来已经选中的选项
可以用select类 的deselect_all方法,清除所有已经选中的选项
# 导入Select类
from selenium.webdriver.support.ui import Select
# 创建Select对象
select=Select(wd.find_element_by_css_selector('#ss_multi'))
# 清除所有已经选中的选项
select.deselect_all()
# 选择小雷老师和小凯老师
select.select_by_visible_text('小雷老师')
select.select_by_visible_text('小凯老师')
七、Xpath选择器
1.语法
(1)绝对路径选择
xpath表达式 /html/body/div
,是一个绝对路径的xpath表达式, 等价于 css表达式 html>body>div
例如:elements = driver.find_elements_by_xpath("/html/body/div")
(2)相对路径选择
xpath前面加 // , 表示从当前节点往下寻找所有的后代元素,不管它在什么位置
//’ 符号也可以继续加在后面,比如,要选择所有的div元素里面的所有的p元素 ,不管div在什么位置,也不管p元素在div下面的什么位置,则可以写成 //div//p
即:elements = driver.find_elements_by_xpath("//div//p")
(3)通配符
星号是一个通配符,对应任意节点名的元素,如果要选择所有div节点的所有直接子节点,可以使用表达式 //div/*
2.根据属性选择
Xpath 可以根据属性来选择元素。根据属性来选择元素是通过这种格式来的 [@属性名=‘属性值’]
3.按次序选择
(1)某类型第几个子元素,例如://p[1]
(2)第几个子元素,例如://div/*[5]
(3)某类型倒数第几个子元素
(4)范围选择
(5)组选择
xpath也有组选择, 是用竖线隔开多个表达式
例如:要选所有的class为single_choice和class为multi_choice的元素,即://*[@class='single_choice'] | //*[@class='multi_choice']
(6)选择父节点
某个元素的父节点用 /… 表示,例如:要选择id 为china的节点的父节点,可以写 //*[@id='china']/..
,还可以继续找上层父节点,即://*[@id='china']/../../..
(7)兄弟节点选择
xpath也可以选择后续兄弟节点,用语法 following-sibling::
例如:要选择class为single_choice的元素的所有后续兄弟节点,//*[@class='single_choice']/following-sibling::*
要选择后续节点中的div节点, 为 //*[@class='single_choice']/following-sibling::div
xpath还可以选择前面的兄弟节点,用语法 preceding-sibling::
例如:要选择class为single_choice的元素的所有前面的兄弟节点 //*[@class='single_choice']/preceding-sibling::*