0


Web自动化Selenium-常见控件操作

搜索框

以百度搜索框为例,我们来看一下搜索框的元素属性。标签类型是<input>

●输入文字:ele.send_keys('storm')。

●清除文字:ele.clear()。

●获取搜索框中的内容:ele.get_property('value')。

控件中的值传给了value属性

●获取元素的属性:ele.get_attribute('name')。

●获取元素的tag name:ele.tag_name。

from selenium import webdriver
from time import sleep

'''
搜索框常见操作
'''
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
#定位百度搜索框
ele = driver.find_element_by_id('kw')
ele.send_keys('storm') # 通过send_keys方法输入内容
sleep(2)
ele.clear() # 通过clear方法清除搜索框中的内容
sleep(2)
ele.send_keys('storm') # 通过send_keys方法再次输入内容
print(ele.get_property('value')) # 获取搜索框中的内容:get_property('value')
print(ele.get_attribute('name')) # 获取元素的属性:get_attribute()
print(ele.tag_name) # 获取元素的tag name:tag_name
sleep(3)
driver.quit()

●clear方法在处理有提示信息(placeholder这个属性)的搜索框的时候很有用,一般需要先使用clear,再使用send_keys

按钮

◆元素属性

我们来看一下按钮的元素属性,常见按钮有3种类型:button按钮、submit按钮、radio按钮。

button按钮

from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get("http://sahitest.com/demo/clicks.htm")
driver.find_element_by_xpath("/html/body/form/input[3]").click()
sleep(2)
text = driver.find_element_by_name("t2").get_attribute('value')
if text == '[CLICK]':
      print('pass')
driver.quit()

submit按钮

from time import sleep

driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
driver.find_element_by_id('kw').send_keys('storm')
driver.find_element_by_id('su').submit() # 对于submit按钮,可以使用submit方法
sleep(2)
driver.quit()

radio按钮

●单击:click方法。●判断是否选中:is_selected方法。

这三种按钮都是input标签,不一样的只是type。

from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get("http://sahitest.com/demo/clicks.htm")

ele = driver.find_element_by_xpath('/html/body/form/input[7]')#注意这种xpath写法很不好
ele.click()
sleep(2)
if ele.is_selected():
      print('pass')
sleep(3)
driver.quit()

button按钮不支持submit方法。

复选框

◆元素属性<input>标签,type="checkbox"

●模拟单击选中复选框:ele.click()。

●模拟按空格键选中复选框:ele.send_keys(Keys.SPACE)。

from selenium import webdriver
from time import sleep
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome()
driver.get("http://sahitest.com/demo/clicks.htm")
ele = driver.find_element_by_xpath('/html/body/ul//input')
ele.click()
sleep(2)
if ele.is_selected():
      print('pass')
sleep(2)
ele.send_keys(Keys.SPACE)  #自己可以手动实践一下,按空格键可以选中或取消选中复选框
sleep(2)
driver.quit()

假如我们想将一组复选框全都选中,该如何操作呢?

示例:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CheckBox</title>
</head>
<body>
下面是一组复选框:
    <br>
    <input type="checkbox" name="a">
    <br>
    <input type="checkbox" name="a">
    <br>
    <input type="checkbox" name="a">
</body>
</html>

from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get('C:\\Users\\Desktop\\my_html.html')
eles = driver.find_elements_by_name('a') # 通过name定位一组元素
for ele in eles: # 循环读取每个复选框
      ele.click()  # 单击
      sleep(2)

driver.quit()

这组复选框都有一个相同的name属性值,因此,可以通过name来定位一组元素,并将其存成一个列表,然后循环读取并操作列表即可

链接

链接是一个标签对,页面中显示的链接文字,就是中间的文字

●获取链接文字:ele.text。

●单击链接:ele.click()。

select下拉列表

下拉列表的tag name是“select”,而下拉列表的选项的tag name是“option”

导包,可以用这两种方法任一个

from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.select import Select

●实例化Select:Select(driver.find_element_by_id('s1Id'))。

●选择下拉选项:select类提供了3种选择某一选项的方法,分别是通过index选择下拉选项——select_by_index(index);通过value值选择下拉选项——select_by_value(value);通过可见text选择下拉选项——select_by_visible_text(text)。

●取消下拉选项:select类提供了4种方法取消原来的选择,分别是通过index取消下拉选项——deselect_by_index(index);通过value值取消下拉选项——deselect_by_value(value);通过可见text取消下拉选项——deselect_by_visible_text(text);全部取消选择——deselect_all()。

●返回选项:返回所有选项——options;返回第一个选中项——first_selected_option;返回所有选中项——all_selected_options。

●判断select选项是否可多选:is_multiple,返回一个布尔值。

选择下拉值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>select下拉列表</title>
    </head>
<body>
<select id="s1Id">
<option></option>
<option value="o1" id="id1">o1</option>
<option value="o2" id="id2">o2</option>
<option value="o3" id="id3">o3</option>
</select>
</body>
</html>
from selenium import webdriver
from time import sleep
from selenium.webdriver.support.ui import Select
driver = webdriver.Chrome()
driver.get('C:\\Users\\Desktop\\my_html.html')
ele = driver.find_element_by_id('s1Id')
# Select(ele).select_by_index(1)#通过 index定位
Select(ele).select_by_value('o2')#通过value属性定位
# Select(ele).select_by_visible_text('o3')
sleep(3)
driver.quit()

●value是<option>标签的一个属性值,并不是显示在下拉列表中的值

●visible_text是在<option>和</option>标签对中间的值,是显示在下拉列表中的值

取消选择

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>可以多选的select下拉列表</title>
</head>
<body>
<select id="s1Id" multiple="multiple">
<option>请选择:</option>
<option value="o1" id="id1">o1</option>
<option value="o2" id="id2">o2</option>
<option value="o3" id="id3">o3</option>
</select>
</body>
</html>

<select>标签多了一个multiple="multiple"的属性,这意味着该下拉列表的选项可以多选。

from selenium import webdriver
from time import sleep
from selenium.webdriver.support.ui import Select
driver = webdriver.Chrome()
driver.get('C:\\Users\\Desktop\\my_html.html')
ele = driver.find_element_by_id('s1Id')
Select(ele).select_by_index(1)#通过 index定位
sleep(2)
Select(ele).deselect_by_index(1)#取消选择
Select(ele).select_by_index(1)
Select(ele).select_by_index(2)
Select(ele).select_by_index(3)
Select(ele).deselect_all()#取消所有选择
sleep(3)
driver.quit()

获取选项

获取所有option,并依次选中

◆select提供了3个属性用于获取选项

Options——返回包含所有选项的列表,其中选项是WebElement元素。

all_selected_options——返回包含所有被选中的选项的列表。

first_selected_option——提供第一个被选中的选项,也可以用于获取下拉列表的默认值。

from selenium import webdriver
from time import sleep
from selenium.webdriver.support.ui import Select
driver = webdriver.Chrome()
driver.get('C:\\Users\\Desktop\\my_html.html')
ele = driver.find_element_by_id('s1Id')
all_options=Select(ele).options #返回所有option
for i in range(len(all_options)):
    Select(ele).select_by_index(i)#循环option依次选中
all=Select(ele).all_selected_options #获取所有被选择的选项
for i in all:
    print(i.text)
driver.quit()

判断select下拉列表中的选项是否可多选

◆Select提供了一个属性,用来判断是否可多选is_multiple——返回一个布尔值,判断select选项是否可多选。

from selenium import webdriver
from time import sleep
from selenium.webdriver.support.ui import Select
driver = webdriver.Chrome()
driver.get('C:\\Users\\Desktop\\my_html.html')
ele = driver.find_element_by_id('s1Id')
print(Select(ele).is_multiple)

表格

一个table标签对应一个表格;“table”里面包含若干“tr”,每个“tr”对应一行;每个“tr”下面包含若干“td”,每个“td”对应一个单元格

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>学习操作表格-1</title>
</head>
<body>
<table border="1">
<tr>
<td>0-0</td>
<td>0-1</td>
<td id="CellWithId">Cell with id</td>
<td>0-3</td>
</tr>
<tr>
<td>1-0</td>
<td>1-1</td>
<td>1-2</td>
<td>1-3</td>
</tr>
<tr>
<td>2-0</td>
<td>2-1</td>
<td>2-2</td>
<td>2-3</td>
</tr>
</table>
<br>
</body>
</html>

如果只是想获取某个单元格中的值,那么像定位普通元素一样定位单元格即可

from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
ele=driver.find_element_by_id('CellWithId')
print(ele.text)

场景二:假如想输出表格中所有单元格的值呢?

思路:先定位页面中的表格对象元素;然后在该表格中,通过tag name = 'tr'找所有行;最后在每行中,通过tag name = 'td'找所有单元格。

from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get('C:\\Users\\Desktop\\my_html.html')
table = driver.find_element_by_xpath('/html/body/table[1]')
rows = table.find_elements_by_tag_name('tr')
cols = rows[0].find_elements_by_tag_name('td')
for i in range(len(rows)):
      for j in range(len(cols)):
            cell = rows[i].find_elements_by_tag_name('td')[j]
            print(cell.text)

driver.quit()

框架

●frame一般用来设置页面布局,将整个页面分成规则的几块,每一块里面包含一个新页面;iframe用来在页面的任何地方插入一个新的页面。

from selenium import webdriver
from time import sleep
import os

driver = webdriver.Chrome()
html_file = 'File:///' + os.getcwd() + os.sep + 'myhtml6_8.html'
driver.get(html_file)
driver.switch_to.frame('iframe1')  # 通过id切换
# driver.switch_to.frame('name1')  # 通过name切换
# driver.switch_to.frame(0) # 通过index切换
driver.find_element_by_id('kw').send_keys('storm') # 尝试定位搜索框,输入文字
sleep(2)
driver.quit()

先定位iframe这个元素,然后切换到目标元素。

from selenium import webdriver
from time import sleep
import os

driver = webdriver.Chrome()
html_file = 'File:///' + os.getcwd() + os.sep + 'myhtml6_8.html'
driver.get(html_file)
ele = driver.find_element_by_xpath('//*[@id="another"]/iframe') # 定位iframe元素
driver.switch_to.frame(ele) # 直接传递元素
driver.find_element_by_id('kw').send_keys('storm')
sleep(2)
driver.quit()

4种从Web页面切换到iframe的方法。

●通过id切换(iframe有id属性):driver.switch_to.frame('iframe1')。

●通过name切换(iframe有name属性,且唯一):driver.switch_to.frame('name1')。

●通过index切换(index从0开始,即0代表页面中第一个iframe):driver.switch_to.frame(0)。

●通过定位元素切换:driver.switch_to.frame(iframe_element)。

●总原则:想操作iframe里面的元素,就要先切换到这个iframe上,然后进行操作;想操作iframe外面的元素,就必须跳出这个iframe。对于嵌套的iframe,进去的时候一层层进,出来的时候可以一层层出,也可以直接跳到最外层。

●切换到父级iframe的方法:switch_to. parent_frame。

●切换到主窗口的方法:switch_to.default_content。

JavaScript弹窗

JavaScript弹窗有3种:Alert、Confirm、Prompt。

这3种JavaScript弹窗其实都是input标签,type为按钮(button),都调用了onclick事件,只不过该事件实现的功能有简单和复杂之分,因此其操作类似。

●Alert弹窗:文字信息+确定按钮。

●Confirm弹窗:文字信息+确定按钮+取消按钮。

●Prompt弹窗:文字信息+文本框+确定按钮+取消按钮。

Alert弹窗

下方代码用来准备一个包含Alert弹窗的页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Alert学习</title>
</head>
<body>
<h2>Alert Test</h2>

<script type="text/javascript">
function showAlert(){
    alert(document.f1.t1.value);
}
</script>
<form name="f1">
    <input type="text" name="t1" value="Alert Message"><br><br>
    <input type="button" name="b1" value="Click For Alert" onclick="showAlert()"><br>
</form>
</body>
</html>

from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
driver.find_element_by_name('b1').click()#点击按钮
sleep(1)
print(driver.switch_to.alert.text)#打印alert的text
driver.switch_to.alert.accept()#点击alert弹窗的确定按钮
sleep(2)
driver.quit()

confirm弹窗

html示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Confirm学习</title>
</head>
<body>
<h4>Confirm Test</h4>

<script type="text/javascript">
function showConfirm(){
    var t1 = document.f1.t1;
    if (confirm("Some question?")){
         t1.value = "oked";
    }else{
         t1.value = "canceled";
    }
}
</script>
<form name="f1">
    <input type="button" name="b1" value="Click For Confirm" onclick="showConfirm()"><br><br>
    <input type="text" name="t1">
</form>
<br>
</body>
</html>
from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
driver.find_element_by_name('b1').click()#点击按钮
sleep(1)
print(driver.switch_to.alert.text)#打印confirm的text
# driver.switch_to.alert.accept()#点击confirm弹窗的确定按钮
driver.switch_to.alert.dismiss()#点击confirm的取消按钮
sleep(2)
driver.quit()

prompt弹窗

from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
driver.find_element_by_name('b1').click() # 单击按钮打开Prompt弹窗
sleep(1)
print(driver.switch_to.alert.text) # 输出Prompt弹窗文字
driver.switch_to.alert.send_keys('storm')
sleep(3)
driver.switch_to.alert.accept() # 单击Prompt弹窗中的"确定"按钮
sleep(2)
driver.find_element_by_name('b1').click() # 单击按钮打开Prompt弹窗
sleep(1)
driver.switch_to.alert.send_keys('shadow')
sleep(1)
driver.switch_to.alert.dismiss()
sleep(2)
driver.quit()

这里有个问题,就是send_keys没有输入到prompt的文本框里,

●使用开发者工具无法查看到JavaScript弹窗中的元素,也就是说Alert弹窗是不属于网页DOM树的,在弹窗中单击是没有反应的。

●在使用switch_to.alert.×××之前,首先要确认弹窗确实是JavaScript弹窗。由于Alert 弹窗不美观(样式不好修改),在项目中经常会使用其他类型的弹窗

非JavaScript弹窗

JavaScript弹窗虽然使用起来很方便,但支持的功能过于简单,某些情况下很难满足项目中的需求,因此还可能会使用其他类型的弹窗。

(1)Windows浏览器弹窗单击某个链接之后可能会打开一个新的浏览器弹窗,注意该弹窗跟之前的弹窗是平行关系,有自己的地址栏、最大化按钮、最小化按钮等,这个很容易分辨。而Alert弹窗更类似父子关系,或者叫从属关系,Alert必须依托于某一个弹窗。对于Windows浏览器弹窗,我们只需要通过窗口句柄切换到目标窗口,然后操作即可。

(2)div弹窗div弹窗是通过网页元素构造成的弹窗。这种弹窗一般比较花哨且内容比较多,可以使用开发者工具查看元素内容

对于这类弹窗,将其视为普通元素去定位就好了

◆注意事项在处理弹窗类元素的时候,需要做好元素是否已经加载的判断,避免由于网络等原因造成弹窗加载慢、元素定位不到等问题。

日期时间控件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>日期时间控件</title>
</head>
<body>
<input type="date" name="name1" id="id1">
</body>
</html>

日期时间控件的外观虽然多种多样,但使用浏览器开发者工具查看,可以发现它就是一个input框。对于input框,我们是不是可以像普通文本框一样直接输入日期

from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
sleep(2)
driver.find_element_by_tag_name('input').send_keys('002020/06/06')
sleep(5)
driver.quit()

◆注意事项

●日期时间控件本身功能是否健全,需要人工去验证,自动化模拟单击实现成本太高(实际上,如果用的是标准化的日期时间控件,已经有大把的团队验证过其功能的健全性了)。

●自动化一般不验证日期时间控件的功能,只需要模拟输入,然后验证其他功能即可(自动化不是万能的,又或者说“物尽其用”即可)。

●有些日期时间控件有readonly属性,在使用send_keys方法之前,我们就需要做点“准备工作”了

文件下载

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件下载</title>
</head>
<body>
<a href="storm.rar" download="storm.rar">下载</a>
</body>
</html>

下载的本质就是一个标签,有点类似链接,点击即可。

如何下载到指定路径?

from selenium import webdriver
from time import sleep
import os

chromeOptions = webdriver.ChromeOptions() # 定义变量,存储Chrome浏览器的设置项
prefs = {"download.default_directory": "D:\\A\\"}  # 指定默认下载路径
chromeOptions.add_experimental_option("prefs", prefs) # 将prefs定义的下载路径应用于浏览器设置
driver = webdriver.Chrome(chrome_options=chromeOptions) # 以自定义的设置项启动浏览器
html_file = 'File:///' + os.getcwd() + os.sep + 'myhtml6_13.html'
driver.get(html_file)
sleep(2)
driver.find_element_by_tag_name('a').click()
sleep(5)
driver.quit()

如何验证确实下载了文件呢?

from selenium import webdriver
from time import sleep
import os

if os.path.exists("D:\\A\\storm.rar"):   # 先判断文件是否存在
      os.remove("D:\\A\\storm.rar")      # 如果存在则删除

chromeOptions = webdriver.ChromeOptions() # 定义变量,存储Chrome浏览器的设置项
prefs = {"download.default_directory": "D:\\A\\"}  # 指定默认下载路径
chromeOptions.add_experimental_option("prefs", prefs) # 将prefs定义的下载路径应用于浏览器设置
driver = webdriver.Chrome(chrome_options=chromeOptions) # 以自定义的设置项启动浏览器
html_file = 'File:///' + os.getcwd() + os.sep + 'myhtml6_13.html'
driver.get(html_file)
sleep(2)
driver.find_element_by_tag_name('a').click()
sleep(5)  # 等待下载完成,然后再去判断文件是否存在
if os.path.exists("D:\\A\\storm.rar"): # 判断文件是否存在
      print("文件下载成功")
driver.quit()

如何比对下载的文件?MD5值。

文件上传

在实际项目中,我们遇到的上传按钮大体上可以分为两种:一种是input控件,另外一种是通过js、flash等实现的且较复杂的非input控件。

input控件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传学习</title>
</head>
<body>
<form name="form1" action="fileUpload.php" method="post" enctype="multipart/form-data">
<label for="file">File:</label>
<input type="file" name="file" id="file" /> 
</form>
</body>
</html>

对于“input类型文件上传”功能,我们可以通过“send_keys”+“文件”的方式跳过对文件选择弹窗的操作。要知道这个文件选择弹窗是Windows弹窗,而WebDriver的操作范围是浏览器,我们是无法让其控制Windows弹窗的。

from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
sleep(2)
driver.find_element_by_id('file').send_keys("C:\\Users\\yangyl13\\Desktop\\test.txt")
sleep(2)
driver.quit()

selenium不支持上传多个文件

非input 型上传控件

对于非input型上传控件,就不能使用send_keys取巧了。这类上传控件种类众多,有用a标签的、有用div的、有用button的、有用object的,我们没有办法直接在网页上处理这些上传操作。唯一的办法就是打开操作系统弹窗,再想办法去处理弹窗。而对于操作系统的弹窗,其涉及的层面已经不是Selenium能解决的了,怎么办?

很简单,用操作系统层面的操作去处理,到这里我们基本找到了处理问题的思路。大致有以下几种方案。

●AutoIt,借助外力,我们去调用其生成的“.au3”或“.exe”文件。

●Python pywin32库,识别弹窗句柄,进而处理弹窗。

●SendKeys库。

注意:当单击type=file的input类型的元素时会报错。

遇到上传文件控件时,看看其是否是input型。如果是,那么恭喜你,可以用send_keys解决。如果碰到了div型的控件,用AutoIt处理也不难。如果还想验证能否同时上传多个文件,那么只能使用pywin32库来处理


本文转载自: https://blog.csdn.net/seanyang_/article/details/127460142
版权归原作者 东方不败就是我 所有, 如有侵权,请联系我们删除。

“Web自动化Selenium-常见控件操作”的评论:

还没有评论