学习网站:白月黑羽
使用Selenium,我们可以通过写出自动化程序,像人一样在浏览器里操作web界面。 比如点击界面按钮,在文本框中输入文字等。而且还能从web界面获取信息,比如获取火车、汽车票务信息,招聘网站职位信息,财经网站股票价格信息等等,然后用程序进行分析处理。Selenium的自动化原理是这样的:
从上图可以看出:我们写的程序的自动化请求通过客户端库里面的编程接口发送给浏览器。比如,我们要模拟用户点击界面按钮, 自动化程序里面就应该调用客户端库相应的函数, 就会发送点击元素的请求给下方的浏览器驱动。 然后,浏览器驱动再转发这个请求给浏览器。这个自动化程序发送给浏览器驱动的请求是HTTP请求。
浏览器驱动接收到我们的自动化程序发送的界面操作请求后,会转发请求给浏览器,让浏览器去执行对应的自动化操作。浏览器执行完操作后,会将自动化的结果返回给浏览器驱动,浏览器驱动再通过HTTP响应的消息返回给我们的自动化程序的客户端库。自动化程序的客户端库 接收到响应后,将结果转化为数据对象返回给我们的代码。我们的程序就可以知道这次自动化操作的结果如何了。
selenium 自动化流程如下:
- 自动化程序调用Selenium客户端库函数(比如点击按钮元素)
- 客户端库会发送Selenium命令给浏览器的驱动程序
- 浏览器驱动程序接收到命令后,驱动浏览器去执行命令
- 浏览器执行命令
- 浏览器驱动程序获取命令执行的结果,返回给我们自动化程序
- 自动化程序对返回结果进行处理
Selenium环境的安装主要安装两样东西: 客户端库和浏览器驱动 。
不同的编程语言选择不同的Selenium客户端库。本文我们使用python,在命令行程序输入:pip install selenium
。或使用国内的豆瓣源:pip install selenium -i https://pypi.douban.com/simple/
edge驱动
下面的代码可以自动的打开Chrome浏览器,并且自动化打开百度网站:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
# 创建一个控制浏览器的对象,即WebDriver对象(可以把它理解为控制了浏览器的遥控器),指明使用chrome浏览器驱动,此时会运行浏览器驱动,并且运行Chrome浏览器。
# 等号右边返回的是WebDriver类型的对象,我们可以通过这个对象来操控浏览器,比如打开网址、选择界面元素等。
wd = webdriver.Chrome(service=Service(r'd:\tools\chromedriver.exe'))# 在python中,r表示\不代表转义字符
# 调用WebDriver对象的get方法 可以让浏览器打开指定网址
wd.get('https://www.baidu.com')
# 程序运行完会自动关闭浏览器,就是很多人说的闪退
# 这里加入等待用户输入,防止闪退
input('等待回车键结束程序')
前面,我们的代码创建WebDriver对象时,需要指定浏览器驱动路径,比如
from selenium.webdriver.chrome.service import Service
wd = webdriver.Chrome(service=Service(r'd:\tools\chromedriver.exe'))
这样写存在几个问题:
解决办法:把浏览器驱动所在目录(比如d:\tools)加入环境变量Path,写代码时,就可以无需指定浏览器驱动路径了,像下面这样:wd = webdriver.Chrome()
。因为,Selenium会自动在环境变量Path指定的那些目录里查找名为chromedriver.exe 的文件。设置完环境变量后,重启IDE(比如 PyCharm) 新的环境变量才会生效。
基本思想:告诉浏览器,你要操作的这个web元素的特征 。
方法:用chrome浏览器访问百度,按F12后,点击下图箭头处的Elements标签,即可查看页面对应的HTML 元素
然后,再点击最左边的图标,如下所示
之后,鼠标在界面上点击哪个元素,就可以查看该元素对应的html标签 了。
下面的代码,可以自动化在浏览器中访问我们的股票搜索网站,并且在输入框中搜索通讯 。
from selenium import webdriver
from selenium.webdriver.common.by import By
# 创建 WebDriver 对象
wd = webdriver.Chrome()
# 调用WebDriver 对象的get方法 可以让浏览器打开指定网址
wd.get('https://www.byhy.net/_files/stock1.html')
# 根据id选择元素,返回的就是该元素对应的WebElement对象,WebElement对象可以看成是对应页面元素的遥控器。
try:
element = wd.find_element(By.ID, 'kw')
element1 = wd.find_element(By.ID, 'kw1')
except NoSuchElementException:
print("元素不存在")
# 通过该 WebElement对象,就可以对页面元素进行操作了
element.send_keys('通讯\n')# 比如输入字符串到这个输入框里
element1.click()# 点击按钮
wd.quit()# 关闭浏览器
页面代码:
<body>
<div class="plant"><span>土豆span>div>
<div class="plant"><span>洋葱span>div>
<div class="plant"><span>白菜span>div>
<div class="animal"><span>狮子span>div>
<div class="animal"><span>老虎span>div>
<div class="animal"><span>山羊span>div>
body>
所有的植物元素都有个class属性 值为 plant。所有的动物元素都有个class属性 值为 animal。如果我们要选择 所有的 动物, 就像下面可以这样写:wd.find_elements(By.CLASS_NAME, 'animal')
find_element和find_elements的区别:
- 使用find_elements选择的是符合条件的所有元素,如果没有符合条件的元素,返回空列表
- 使用find_element选择的是符合条件的第一个元素,如果没有符合条件的元素,抛出NoSuchElementException异常
from selenium import webdriver
from selenium.webdriver.common.by import By
# 创建 WebDriver 实例对象,指明使用chrome浏览器驱动
wd = webdriver.Chrome()
# WebDriver 实例对象的get方法 可以让浏览器打开指定网址
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')
# 根据 class name 选择元素,返回的是 一个列表,里面都是class属性值为animal的元素对应的WebElement对象
elements = wd.find_elements(By.CLASS_NAME, 'animal')
# 取出列表中的每个WebElement对象,打印出其text属性的值,text属性就是该WebElement对象对应的元素在网页中的文本内容
for element in elements:
print(element.text)# 获取该元素 在网页中的文本内容
通过指定参数为By.TAG_NAME
,选择所有的tag名为div的元素:
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')
# 根据 tag name 选择元素,返回的是 一个列表
# 里面 都是 tag 名为 div 的元素对应的 WebElement对象
elements = wd.find_elements(By.TAG_NAME, 'div')
# 取出列表中的每个 WebElement对象,打印出其text属性的值
# text属性就是该 WebElement对象对应的元素在网页中的文本内容
for element in elements:
print(element.text)
WebDriver对象选择元素的范围是整个web页面, 而WebElement对象选择元素的范围是 该元素的内部。
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')
element = wd.find_element(By.ID,'container')
# 限制 选择元素的范围是 id 为 container 元素的内部。
spans = element.find_elements(By.TAG_NAME, 'span')
for span in spans:
print(span.text)
输出结果就只有:
内层11
内层12
内层21
在我们进行网页操作的时候, 有的元素内容不是可以立即出现的,可能会等待一段时间。比如我们的股票搜索示例页面,搜索一个股票名称,我们点击搜索后,浏览器需要把这个搜索请求发送给服务器,服务器进行处理后,再把搜索结果返回给我们。有以下两种解决方案:
sleep
来等待几秒钟, 等百度服务器返回结果后,再去选择 id 为1 的元素from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('https://www.byhy.net/_files/stock1.html')
element = wd.find_element(By.ID, 'kw')
element.send_keys('通讯\n')
# 等待 1 秒
from time import sleep
sleep(1)
element = wd.find_element(By.ID,'1')
print(element.text)
但是等待时间的长短不好确定
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
# 后续所有的find_element或者find_elements之类的方法调用都会采用上面的策略:如果找不到元素,每隔半秒钟再去界面上查看一次,直到找到该元素,或者过了10秒最大时长。
wd.implicitly_wait(10)
wd.get('https://www.byhy.net/_files/stock1.html')
element = wd.find_element(By.ID, 'kw')
element.send_keys('通讯\n')
# 返回页面 ID为1 的元素
element = wd.find_element(By.ID,'1')
print(element.text)
操控元素通常包括
当我们调用 WebElement 对象的 click 方法去点击 元素的时候, 浏览器接收到自动化命令,点击的是该元素的 中心点 位置 。
调用元素WebElement对象的 click方法,如果我们要 把输入框中已经有的内容清除掉,可以使用WebElement对象的clear方法
element = wd.find_element(By.ID, "input1")
element.clear() # 清除输入框已有的字符串
element.send_keys('白月黑羽') # 输入新字符串
通过WebElement对象的 text 属性,可以获取元素 展示在界面上的 文本内容。
element = wd.find_element(By.ID, 'animal')
print(element.text)
通过WebElement对象的 get_attribute 方法来获取元素的属性值,比如要获取元素属性class的值,就可以使用element.get_attribute('class')
element = wd.find_element(By.ID, 'input_name')
print(element.get_attribute('class'))
执行完自动化代码,如果想关闭浏览器窗口可以调用WebDriver对象的quit方法:wd.quit()
要获取整个元素对应的HTML文本内容,可以使用element.get_attribute('outerHTML')
,如果,只是想获取某个元素内部的HTML文本内容,可以使用element.get_attribute('innerHTML')
对于input输入框的元素,要获取里面的输入文本,这时可以使用 element.get_attribute('value')
element = wd.find_element(By.ID, "input1")
print(element.get_attribute('value')) # 获取输入框中的文本
通过WebElement对象的text属性,可以获取元素展示在界面上的文本内容。但是,有时候,元素的文本内容没有展示在界面上,或者没有完全完全展示在界面上。 这时,用WebElement对象的text属性,获取文本内容,就会有问题,我们可以尝试使用element.get_attribute('innerText')
,或者 element.get_attribute('textContent')
使用innerText和textContent的区别是,前者只显示元素可见文本内容,后者显示所有内容(包括display属性为none的部分)
通过 CSS Selector 选择单个元素的方法是:find_element(By.CSS_SELECTOR, CSS Selector参数)
,选择所有元素的方法是:find_elements(By.CSS_SELECTOR, CSS Selector参数)
一、根据tag名选择元素直接写上tag名即可,比如要选择所有的tag名为div的元素:elements = wd.find_elements(By.CSS_SELECTOR, 'div')
,等价于elements = wd.find_elements(By.TAG_NAME, 'div')
二、根据id属性选择元素的语法是在id号前面加上一个井号: #id值
,假如页面为:,我们想在id为searchtext的输入框中输入文本【你好】
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')
element = wd.find_element(By.CSS_SELECTOR, '#searchtext')
element.send_keys('你好')
三、根据class属性选择元素的语法是在class值前面加上一个点: .class值
,假如页面代码为:
<body>
<div class="plant"><span>土豆span>div>
<div class="plant"><span>洋葱span>div>
<div class="plant"><span>白菜span>div>
<div class="animal"><span>狮子span>div>
<div class="animal"><span>老虎span>div>
<div class="animal"><span>山羊span>div>
body>
要选择所有class属性值为animal的元素动物除了这样写:elements = wd.find_elements(By.CLASS_NAME, 'animal')
,还可以这样写:elements = wd.find_elements(By.CSS_SELECTOR, '.animal')
页面代码:
<div id='container'>
<div id='layer1'>
<div id='inner11'>
<span>内层11span>
div>
<div id='inner12'>
<span>内层12span>
div>
div>
<div id='layer2'>
<div id='inner21'>
<span>内层21span>
div>
div>
div>
说明:
后代元素也包括了直接子元素,比如id为layer1和layer2的两个div元素,也可以说是id为container的div元素的直接子元素,同时也是后代子元素
如果元素2是元素1的直接子元素,CSS Selector选择直接子元素的语法是这样的:元素1 > 元素2
,也支持更多层级的选择:元素1 > 元素2 > 元素3 > 元素4
,就是选择元素1里面的子元素元素2里面的子元素元素3里面的子元素元素4,最终选择的元素是元素4
如果元素2是元素1的后代元素,CSS Selector选择后代元素的语法是这样的:元素1 元素2
,中间是一个或者多个空格隔开,也支持更多层级的选择, 比如元素1 元素2 元素3 元素4
,最终选择的元素是 元素4
css 选择器支持通过任何属性来选择元素,语法是用一个方括号[]
,假如想根据href选择苏ICP备88885574号
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')
# 根据属性选择元素
element = wd.find_element(By.CSS_SELECTOR, '[href="http://www.miitbeian.gov.cn"]')# 属性值用单引号,双引号都可以。
# 打印出元素对应的html
print(element.get_attribute('outerHTML'))
说明:
div[class='SKnet']
表示选择所有标签名为div,且class属性值为SKnet的元素。[href]
, 表示选择所有具有属性名为href
的元素,不管它们的值是什么。a[href*="miitbeian"]
a[href^="http"]
a[href$="gov.cn"]
沙漠之鹰
,CSS选择器 可以指定选择的元素要同时具有多个属性的限制:div[class=misc][ctype=gun]
假如我们要验证#bottom > .footer2 a
是否选中苏ICP备88885574号
,使用开发者工具,点击Elements标签后, 同时按Ctrl+F,就会出现下图箭头处的搜索框
我们可以在里面输入任何CSS Selector表达式,如果能选择到元素, 右边的的红色方框里面就会显示出类似2of3这样的内容。
如果我们要同时选择所有class为plant和class为animal的元素,可以使用逗号,这称之为组选择:.plant , .animal
。再比如,我们要同时选择所有tag名为div的元素和id为BYHY的元素,就可以像这样写:div,#BYHY
,对应的selenium代码如下
elements = wd.find_elements(By.CSS_SELECTOR, 'div,#BYHY')
for element in elements:
print(element.text)
如果我们要选择所有id为t1里面的span和p元素:#t1 > span , #t1 > p
html代码如下:
<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>
如果我们要选择上图所有class="plant"
的标签,这些元素是在一个叫iframe的元素中的。在html语法中,frame元素或者iframe元素的内部会包含一个被嵌入的另一份html文档。在我们使用selenium打开一个网页时,我们的操作范围是当前的html, 并不包含被嵌入的html文档里面的内容,如果我们要操作被嵌入的html文档中的元素,就必须切换操作范围到被嵌入的文档中:使用WebDriver对象的switch_to属性:wd.switch_to.frame(frame_reference)
,其中,frame_reference可以是frame元素的属性、name或者ID,比如这里,就可以填写iframe元素的id值‘frame1’或者name属性值‘innerFrame’:wd.switch_to.frame('frame1')
或者wd.switch_to.frame('innerFrame')
,也可以填写frame所对应的WebElement对象。我们可以根据frame的元素位置或者属性特性,使用find系列的方法,选择到该元素,得到对应的WebElement对象:wd.switch_to.frame(wd.find_element(By.TAG_NAME, "iframe"))
,然后,就可以进行后续操作frame里面的元素了。如果我们已经切换到某个iframe里面进行操作了,那么后续选择和操作界面元素 就都是在这个frame里面进行的。这时候,如果我们又需要操作 主html(我们把最外部的html称之为主html) 里面的元素了呢?怎么切换回原来的主html呢?使用:wd.switch_to.default_content()
。操作完 frame里面的元素后, 需要 点击 主html 里面的按钮,完整代码就可以这样写:
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('https://cdn2.byhy.net/files/selenium/sample2.html')
# 先根据name属性值 'innerFrame',切换到iframe中
wd.switch_to.frame('innerFrame')
# 根据 class name 选择元素,返回的是 一个列表
elements = wd.find_elements(By.CLASS_NAME, 'plant')
for element in elements:
print(element.text)
# 切换回 最外部的 HTML 中
wd.switch_to.default_content()
# 然后再 选择操作 外部的 HTML 中 的元素
wd.find_element_by_id('outerbutton').click()
wd.quit()
点击一个链接 或者 按钮,就会打开一个 新窗口 。在打开的网页中,点击 链接 “访问bing网站” , 就会弹出一个新窗口,即使新窗口打开了, 我们的 WebDriver对象对应的还是老窗口,自动化操作也还是在老窗口进行,如果我们要到新的窗口里面操作,可以使用Webdriver对象的switch_to属性的window方法:wd.switch_to.window(handle)
,handle需要传入什么呢?
WebDriver对象有window_handles属性,是一个列表对象, 里面包括了当前浏览器里面所有的窗口句柄(可以把句柄想象成对应网页窗口的一个ID),那么我们就可以通过 类似下面的代码,
for handle in wd.window_handles:
# 先切换到该窗口
wd.switch_to.window(handle)
# 得到该窗口的标题栏字符串,判断是不是我们要操作的那个窗口
if 'Bing' in wd.title:
# 如果是,那么这时候WebDriver对象就是对应的该该窗口,正好,跳出循环,
break
上述代码依次获取wd.window_handles
里面的所有句柄对象,并且调用 wd.switch_to.window(handle)
方法切入到每个窗口,然后检查里面该窗口对象的属性(可以是标题栏,地址栏),判断是不是我们要操作的那个窗口,如果是,就跳出循环。同样的,如果我们在新窗口 操作结束后,怎么回到原来的窗口?我们可以仍然使用上面的方法,依次切入窗口,然后根据标题栏之类的属性值判断。还有更省事的方法,因为我们一开始就在原来的窗口里面,我们知道进入新窗口操作完后,还要回来,可以事先保存该老窗口的句柄,使用如下方法
# mainWindow变量保存当前窗口的句柄
mainWindow = wd.current_window_handle
切换到新窗口操作完后,就可以直接像下面这样,将driver对应的对象返回到原来的窗口
#通过前面保存的老窗口的句柄,自己切换到老窗口
wd.switch_to.window(mainWindow)
直接用WebElement的click方法,模拟用户点击即可。比如,我们要在下面的html中:
<div id="s_radio">
<input type="radio" name="teacher" value="小江老师">小江老师<br>
<input type="radio" name="teacher" value="小雷老师">小雷老师<br>
<input type="radio" name="teacher" value="小凯老师" checked="checked">小凯老师
div>
先打印当前选中的老师名字,再选择小雷老师,对应的代码如下
# 获取当前选中的元素
element = wd.find_element(By.CSS_SELECTOR,
'#s_radio input[name="teacher"]:checked')# :checked表示选择checked状态的元素,对 radio和checkbox类型的input有效
print('当前选中的是: ' + element.get_attribute('value'))
# 点选 小雷老师
wd.find_element(By.CSS_SELECTOR,
'#s_radio input[value="小雷老师"]').click()
直接用WebElement的click方法,模拟用户点击选择。需要注意的是,要选中checkbox的一个选项,必须先获取当前该复选框的状态,如果该选项已经勾选了,就不能再点击,否则反而会取消选择。比如我们要在下面的html中
<div id="s_checkbox">
<input type="checkbox" name="teacher" value="小江老师">小江老师<br>
<input type="checkbox" name="teacher" value="小雷老师">小雷老师<br>
<input type="checkbox" name="teacher" value="小凯老师" checked="checked">小凯老师
div>
选中小雷老师:
# 先把 已经选中的选项全部点击一下
elements = wd.find_elements(By.CSS_SELECTOR,
'#s_checkbox input[name="teacher"]:checked')
for element in elements:
element.click()
# 再点击 小雷老师
wd.find_element(By.CSS_SELECTOR,
"#s_checkbox input[value='小雷老师']").click()
对于Select选择框,Selenium专门提供了一个Select类进行操作。Select类提供了如下的方法
select_by_value
:根据选项的value属性值选择元素。比如针对
,就可以根据foo这个值选择该选项:s.select_by_value('foo')
select_by_index
:根据选项的次序(从0开始)选择元素select_by_visible_text
:根据选项的可见文本选择元素。比如针对
,就可以根据Bar这个内容,选择该选项s.select_by_visible_text('Bar')
deselect_by_value
:根据选项的value属性值, 去除选中元素deselect_by_index
:根据选项的次序,去除选中元素deselect_by_visible_text
:根据选项的可见文本,去除选中元素deselect_all
:去除选中所有元素不管原来选的是什么,直接用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类的deselect_all方法,清除所有已经选中的选项。然后再通过select_by_visible_text方法选择小雷老师和小凯老师:
# 导入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("小凯老师")
如果想要进行鼠标右键点击、双击、移动鼠标到某个元素、鼠标拖拽等操作,可以通过Selenium提供的ActionChains类来实现。百度首页的右上角有个更多产品选项:
如果我们把鼠标放在上边,就会弹出下面的糯米、音乐、图片等图标。使用ActionChains 来模拟鼠标移动操作的代码如下:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.implicitly_wait(5)
driver.get('https://www.baidu.com/')
from selenium.webdriver.common.action_chains import ActionChains
ac = ActionChains(driver)
# 鼠标移动到 元素上
ac.move_to_element(
driver.find_element(By.CSS_SELECTOR, '[name="tj_briicon"]')
).perform()
我们可以直接让浏览器运行一段javascript代码,并且得到返回值:
# 直接执行 javascript,里面可以直接用return返回我们需要的数据
nextPageButtonDisabled = driver.execute_script(
'''
ele = document.querySelector('.soupager > button:last-of-type');
return ele.getAttribute('disabled')
''')
# 返回的数据转化为Python中的数据对象进行后续处理
if nextPageButtonDisabled == 'disabled': # 是最后一页
return True
else: # 不是最后一页
return False
有时,自动化的网页内容很长,或者很宽,超过一屏显示,如果我们要点击的元素不在窗口可见区内,新版本的selenium协议,浏览器发现要操作(比如点击操作)的元素,不在可见区内,往往会操作失败,这时可以调用execute_script直接执行js代码,让该元素出现在窗口可见区正中:driver.execute_script("arguments[0].scrollIntoView({block:'center',inline:'center'})", job)
,其中arguments[0]
,就指代了后面的第一个参数job对应的js对象,js对象的scrollIntoView方法,就是让元素滚动到可见部分
block:‘center’ 指定垂直方向居中
inline:‘center’ 指定水平方向居中
比如我们前面讲的百度首页的右上角,有个更多产品选项,如果我们把鼠标放在上边,就会弹出下面的糯米、音乐、图片等图标。如果我们要用selenium自动化点击糯米图标,就需要F12查看这个元素的特征。但是当我们的鼠标从糯米图标移开, 这个栏目就整个消失了, 就没法查看其对应的HTML。我们可以在浏览器的console中输入以下代码:setTimeout(function(){debugger}, 5000)
并回车,执行后, 立即将鼠标放在界面右上角更多产品处。这时候,就会弹出下面的糯米、音乐、图片等图标。然后,我们仔细等待5秒到了以后,界面就会因为执行了debugger命令而被冻住。然后,我们就可以点击开发者工具栏的查看箭头, 再去点击糯米图标,查看其属性了。
自动化的时候,代码模拟用户点击OK按钮:driver.switch_to.alert.accept()
,程序获取弹出对话框中的信息内容:driver.switch_to.alert.text
,完整示例代码:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.implicitly_wait(5)
driver.get('https://cdn2.byhy.net/files/selenium/test4.html')
# --- alert ---
driver.find_element(By.ID, 'b1').click()
# 打印 弹出框 提示信息
print(driver.switch_to.alert.text)
# 点击 OK 按钮
driver.switch_to.alert.accept()
selenium提供如下方法模拟用户点击 OK 或者 Cancel 按钮:
driver.switch_to.alert.accept()
driver.switch_to.alert.dismiss()
完整示例代码:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.implicitly_wait(5)
driver.get('https://cdn2.byhy.net/files/selenium/test4.html')
# --- confirm ---
driver.find_element(By.ID, 'b2').click()
# 打印 弹出框 提示信息
print(driver.switch_to.alert.text)
# 点击 OK 按钮
driver.switch_to.alert.accept()
driver.find_element(By.ID, 'b2').click()
# 点击 取消 按钮
driver.switch_to.alert.dismiss()
Prompt弹出框是需要用户输入一些信息并提交上去,调用driver.switch_to.alert.send_keys('这里面写要提交的内容')
即可,完整示例代码如下:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.implicitly_wait(5)
driver.get('https://cdn2.byhy.net/files/selenium/test4.html')
# --- prompt ---
driver.find_element(By.ID, 'b3').click()
# 获取 alert 对象
alert = driver.switch_to.alert
# 打印 弹出框 提示信息
print(alert.text)
# 输入信息,并且点击 OK 按钮 提交
alert.send_keys('web自动化 - selenium')
alert.accept()
# 点击 Cancel 按钮 取消
driver.find_element(By.ID, 'b3').click()
alert = driver.switch_to.alert
alert.dismiss()
有些弹窗并非浏览器的alert窗口,而是html元素,此时只需要通过之前介绍的选择器选中并进行相应的操作就可以了。
有时间我们需要获取窗口的属性和相应的信息,并对窗口进行控制
获取窗口大小:driver.get_window_size()
改变窗口大小:driver.set_window_size(x, y)
使用WebDriver的title属性来获取当前窗口的标题栏字符串:driver.title
获取当前窗口URL地址:driver.current_url
例如,访问网易,并获取当前窗口的标题和URL
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(5)
# 打开网站
driver.get('https://www.163.com')
# 获取网站标题栏文本
print(driver.title)
# 获取网站地址栏文本
print(driver.current_url)
把浏览器屏幕内容保存为图片文件,比如,做自动化测试时,一个测试用例检查点发现错误,我们可以截屏为文件,以便测试结束时进行人工核查。可以使用WebDriver的get_screenshot_as_file
方法来截屏并保存为图片:
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(5)
# 打开网站
driver.get('https://www.baidu.com/')
# 截屏保存为图片文件
driver.get_screenshot_as_file('1.png')
我们可以通过desired_capabilities参数,指定以手机模式打开chrome浏览器,参考代码如下:
from selenium import webdriver
mobile_emulation = { "deviceName": "Nexus 5" }
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
driver = webdriver.Chrome( desired_capabilities = chrome_options.to_capabilities())
driver.get('http://www.baidu.com')
input()
driver.quit()
网站页面上传文件的功能是通过type属性为file的HTML input元素实现的:。使用selenium自动化上传文件,我们只需要定位到该input元素,然后通过
send_keys
方法传入要上传的文件路径即可:
# 先定位到上传文件的 input 元素
ele = wd.find_element(By.CSS_SELECTOR, 'input[type=file]')
# 再调用 WebElement 对象的 send_keys 方法
ele.send_keys(r'h:\g02.png')
如果需要上传多个文件,可以多次调用send_keys:
ele = wd.find_element(By.CSS_SELECTOR, 'input[type=file]')
ele.send_keys(r'h:\g01.png')
ele.send_keys(r'h:\g02.png')
但是,有的网页上传,是没有file类型的input元素的。如果是Windows上的自动化,可以采用 Windows 平台专用的方法:执行pip install pypiwin32
,确保 pywin32 已经安装,然后参考如下示例代码:
# 找到点击上传的元素,点击
driver.find_element(By.CSS_SELECTOR, '.dropzone').click()
sleep(2) # 等待上传选择文件对话框打开
# 直接发送键盘消息给 当前应用程序,
# 前提是浏览器必须是当前应用
import win32com.client
shell = win32com.client.Dispatch("WScript.Shell")
# 输入文件路径,最后的'\n',表示回车确定,也可能时 '\r' 或者 '\r\n'
shell.Sendkeys(r"h:\a2.png" + '\n')
sleep(1)
XPath (XML Path Language) 是由国际标准化组织W3C指定的,用来在 XML 和 HTML 文档中选择节点的语言。