整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

selenium超全教程(4)-持续更新中

选与多选

单选比较好操作,先定位需要单选的某个元素,然后点击一下即可。

多选好像也比较容易,依次定位需要选择的元素,点击即可。

下拉框

下拉框的操作相对复杂一些,需要用到Select模块。

先导入该类

from selenium.webdriver.support.select import Select

在select模块中有以下定位方法

'''1、三种选择某一选项项的方法'''


select_by_index()           # 通过索引定位;注意:index索引是从“0”开始。
select_by_value()           # 通过value值定位,value标签的属性值。
select_by_visible_text()    # 通过文本值定位,即显示在下拉框的值。


'''2、三种返回options信息的方法'''


options                     # 返回select元素所有的options
all_selected_options        # 返回select元素中所有已选中的选项
first_selected_options      # 返回select元素中选中的第一个选项                  




'''3、四种取消选中项的方法'''


deselect_all                # 取消全部的已选择项
deselect_by_index           # 取消已选中的索引项
deselect_by_value           # 取消已选中的value值
deselect_by_visible_text    # 取消已选中的文本值

测试页面

<html>


<body>


<form>
<select name="球">
<option value="篮球">篮球</option>
<option value="足球" selected="">足球</option>
<option value="排球">排球</option>
<option value="羽毛球">羽毛球</option>
</select>
</form>


</body>
</html>

然后,再演示下拉框的不同选择的方式

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


url = 'file:///C:/Users/Gdc/Desktop/ball.html'


browser = webdriver.Chrome()


browser.get(url)
time.sleep(2)


# 根据索引选择
Select(browser.find_element_by_name("球")).select_by_index("2")
time.sleep(2)
# 根据value值选择
Select(browser.find_element_by_name("球")).select_by_value("羽毛球")
time.sleep(2)
# 根据文本值选择
Select(browser.find_element_by_name("球")).select_by_visible_text("足球")
time.sleep(2)


# 关闭浏览器
browser.close()

多窗口切换之Frame切换

Selenium打开一个页面之后,默认是在父页面进行操作,此时如果这个页面还有子页面,想要获取子页面的节点元素信息则需要切换到子页面进行擦走,这时候switch_to.frame()就来了。如果想回到父页面,用switch_to.parent_frame()即可。

模拟鼠标操作之左键、右键与双击

既然是模拟浏览器操作,自然也就需要能模拟鼠标的一些操作了,这里需要导入ActionChains 类。

from selenium.webdriver.common.action_chains import ActionChains

左键

这个其实就是页面交互操作中的点击click()操作。

右键

context_click()

from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
import time  


browser = webdriver.Chrome()
browser.get(r'https://www.baidu.com')  
time.sleep(2)


# 定位到要右击的元素,这里选的新闻链接
right_click = browser.find_element_by_link_text('新闻')


# 执行鼠标右键操作
ActionChains(browser).context_click(right_click).perform()
time.sleep(2)


# 关闭浏览器
browser.close()

在上述操作中

ActionChains(browser):调用ActionChains()类,并将浏览器驱动browser作为参数传入
context_click(right_click):模拟鼠标双击,需要传入指定元素定位作为参数
perform():执行ActionChains()中储存的所有操作,可以看做是执行之前一系列的操作

双击

double_click()

from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
import time  


browser = webdriver.Chrome()
browser.get(r'https://www.baidu.com')  
time.sleep(2)


# 定位到要双击的元素
double_click = browser.find_element_by_css_selector('#bottom_layer > div > p:nth-child(8) > span')


# 双击
ActionChains(browser).double_click(double_click).perform()
time.sleep(15)


# 关闭浏览器
browser.close()

模拟鼠标操作之拖拽

drag_and_drop(source,target)拖拽操作嘛,开始位置和结束位置需要被指定,这个常用于滑块类验证码的操作之类。

from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
import time  


browser = webdriver.Chrome()
url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)  
time.sleep(2)


browser.switch_to.frame('iframeResult')


# 开始位置
source = browser.find_element_by_css_selector("#draggable")


# 结束位置
target = browser.find_element_by_css_selector("#droppable")


# 执行元素的拖放操作
actions = ActionChains(browser)
actions.drag_and_drop(source, target)
actions.perform()
# 拖拽
time.sleep(15)


# 关闭浏览器
browser.close()

模拟鼠标操作之悬停move_to_element

from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
import time  


browser = webdriver.Chrome()
url = 'https://www.baidu.com'
browser.get(url)  
time.sleep(2)


# 定位悬停的位置
move = browser.find_element_by_css_selector("#form > span.bg.s_ipt_wr.new-pmd.quickdelete-wrap > span.soutu-btn")


# 悬停操作
ActionChains(browser).move_to_element(move).perform()
time.sleep(5)


# 关闭浏览器
browser.close()

模拟键盘操作

selenium中的Keys()类提供了大部分的键盘操作方法,通过send_keys()方法来模拟键盘上的按键。

引入Keys类

from selenium.webdriver.common.keys import Keys

常见的键盘操作

send_keys(Keys.BACK_SPACE):删除键(BackSpace)

send_keys(Keys.SPACE):空格键(Space)

send_keys(Keys.TAB):制表键(TAB)

send_keys(Keys.ESCAPE):回退键(ESCAPE)

send_keys(Keys.ENTER):回车键(ENTER)

send_keys(Keys.CONTRL,'a'):全选(Ctrl+A)

send_keys(Keys.CONTRL,'c'):复制(Ctrl+C)

send_keys(Keys.CONTRL,'x'):剪切(Ctrl+X)

send_keys(Keys.CONTRL,'v'):粘贴(Ctrl+V)

send_keys(Keys.F1):键盘F1

send_keys(Keys.F12):键盘F12

实例操作演示:

定位需要操作的元素,然后操作即可!

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


browser = webdriver.Chrome()
url = 'https://www.baidu.com'
browser.get(url)  
time.sleep(2)


# 定位搜索框
input = browser.find_element_by_class_name('s_ipt')
# 输入python
input.send_keys('python')
time.sleep(2)


# 回车
input.send_keys(Keys.ENTER)
time.sleep(5)


# 关闭浏览器
browser.close()

延时等待

如果遇到使用ajax加载的网页,页面元素可能不是同时加载出来的,这个时候尝试在get方法执行完成时获取网页源代码可能并非浏览器完全加载完成的页面。所以,这种情况下需要设置延时等待一定时间,确保全部节点都加载出来。

等待有三种方式:强制等待、隐式等待和显式等待

1.强制等待

直接time.sleep(n)强制等待n秒,在执行get方法之后执行。

2.隐式等待

implicitly_wait()设置等待时间,如果到时间有元素节点没有加载出来,就会抛出异常。

from selenium import webdriver


browser = webdriver.Chrome()


# 隐式等待,等待时间10秒
browser.implicitly_wait(10)  


browser.get('https://www.baidu.com')
print(browser.current_url)
print(browser.title)


# 关闭浏览器
browser.close()

3. 显式等待

设置一个等待时间和一个条件,在规定时间内,每隔一段时间查看下条件是否成立,如果成立那么程序就继续执行,否则就抛出一个超时异常。

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time


browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
# 设置等待时间10s
wait = WebDriverWait(browser, 10)
# 设置判断条件:等待id='kw'的元素加载完成
input = wait.until(EC.presence_of_element_located((By.ID, 'kw')))
# 在关键词输入:关键词
input.send_keys('Python')


# 关闭浏览器
time.sleep(2)
browser.close()

WebDriverWait的参数说明:

WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)

driver: 浏览器驱动

timeout: 超时时间,等待的最长时间(同时要考虑隐性等待时间)

poll_frequency: 每次检测的间隔时间,默认是0.5秒

ignored_exceptions:超时后的异常信息,默认情况下抛出NoSuchElementException异常

until(method,message='')

method: 在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是False

message: 如果超时,抛出TimeoutException,将message传入异常

until_not(method,message='')

until_not 与until相反,until是当某元素出现或什么条件成立则继续执行,until_not是当某元素消失或什么条件不成立则继续执行,参数也相同。


其他等待条件

from selenium.webdriver.support import expected_conditions as EC


# 判断标题是否和预期的一致
title_is
# 判断标题中是否包含预期的字符串
title_contains


# 判断指定元素是否加载出来
presence_of_element_located
# 判断所有元素是否加载完成
presence_of_all_elements_located


# 判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0,传入参数是元组类型的locator
visibility_of_element_located
# 判断元素是否可见,传入参数是定位后的元素WebElement
visibility_of
# 判断某个元素是否不可见,或是否不存在于DOM树
invisibility_of_element_located


# 判断元素的 text 是否包含预期字符串
text_to_be_present_in_element
# 判断元素的 value 是否包含预期字符串
text_to_be_present_in_element_value


#判断frame是否可切入,可传入locator元组或者直接传入定位方式:id、name、index或WebElement
frame_to_be_available_and_switch_to_it


#判断是否有alert出现
alert_is_present


#判断元素是否可点击
element_to_be_clickable


# 判断元素是否被选中,一般用在下拉列表,传入WebElement对象
element_to_be_selected
# 判断元素是否被选中
element_located_to_be_selected
# 判断元素的选中状态是否和预期一致,传入参数:定位后的元素,相等返回True,否则返回False
element_selection_state_to_be
# 判断元素的选中状态是否和预期一致,传入参数:元素的定位,相等返回True,否则返回False
element_located_selection_state_to_be


#判断一个元素是否仍在DOM中,传入WebElement对象,可以判断页面是否刷新了
staleness_of

运行JavaScript

还有一些操作,比如下拉进度条,模拟javaScript,使用execute_script方法来实现。

from selenium import webdriver


browser = webdriver.Chrome()
# 知乎发现页
browser.get('https://www.zhihu.com/explore')


browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')

Cookie

在selenium使用过程中,还可以很方便对Cookie进行获取、添加与删除等操作。

from selenium import webdriver


browser = webdriver.Chrome()
# 知乎发现页
browser.get('https://www.zhihu.com/explore')
# 获取cookie
print(f'Cookies的值:{browser.get_cookies()}')
# 添加cookie
browser.add_cookie({'name':'球类', 'value':'足球'})
print(f'添加后Cookies的值:{browser.get_cookies()}')
# 删除cookie
browser.delete_all_cookies()
print(f'删除后Cookies的值:{browser.get_cookies()}')

输出:

Cookies的值:[{'domain': '.zhihu.com', 'httpOnly': False, 'name': 'Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49', 'path': '/', 'secure': False, 'value': '1640537860'}, {'domain': '.zhihu.com', ...]
添加后Cookies的值:[{'domain': 'www.zhihu.com', 'httpOnly': False, 'name': '球类', 'path': '/', 'secure': True, 'value': '足球'}, {'domain': '.zhihu.com', 'httpOnly': False, 'name': 'Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49', 'path': '/', 'secure': False, 'value': '1640537860'}, {'domain': '.zhihu.com',...]
删除后Cookies的值:[]

希望本文对你有所帮助~~如果对软件测试、接口测试、自动化测试、面试经验交流感兴趣可以私聊我或关注公众号“特斯汀软件测试”。免费领取最新软件测试大厂面试资料和Python自动化、接口、框架搭建学习资料!技术大牛解惑答疑,同行一起交流。

用JavaScript访问和操作的HTML DOM对象的例子。

Document 对象

  • 使用 document.write() 输出文本

  • 使用 document.write() 输出 HTML

  • 返回文档中锚的数目

  • 返回文档中第一个锚的 innerHTML

  • 返回文档中表单的数目

  • 返回文档中第一个表单的名字

  • 返回文档中的图像数

  • 返回文档中第一个图像的ID

  • 返回文档中的链接数

  • 返回文档中的第一个链接的ID

  • 返回文档中的所有cookies的名称/值对

  • 返回加载的文档的服务器域名

  • 返回文档的最后一次修改时间

  • 返回加载的当前文档的URL

  • 返回文档的标题

  • 返回文档的完整的URL

  • 打开输出流,向流中输入文本

  • write() 和 writeln()的不同

  • 用指定的ID弹出一个元素的innerHTML

  • 用指定的Name弹出元素的数量

  • 用指定的tagname弹出元素的数量

Anchor 对象

  • 返回和设置链接的charset属性

  • 返回和设置链接的href属性

  • 返回和设置链接的hreflang属性

  • 返回一个锚的名字

  • 返回当前的文件和链接的文档之间的关系

  • 改变链接的target属性

  • 返回一个链接的type属性的值

Area 对象

  • 返回图像映射某个区域的替代文字

  • 返回图像映射某个区域的坐标

  • 返回一个区域的href属性的锚部分

  • 返回的主机名:图像映射的某个区域的端口

  • 返回图像映射的某个区域的hostname

  • 返回图像映射的某个区域的port

  • 返回图像映射的某个区域的href

  • 返回图像映射的某个区域的pathname

  • 返回图像映射的某个区域的protocol

  • 返回一个区域的href属性的querystring部分

  • 返回图像映射的某个区域的shape

  • 返回图像映射的某个区域的target的值

Base 对象

  • 返回页面上所有相对URL的基URL

  • 返回页面上所有相对链接的基链接

Button 对象

  • 当点击完button不可用

  • 返回一个button的name

  • 返回一个button的type

  • 返回一个button的value

  • 返回一个button所属表的ID

Form 对象

  • 返回一个表单中所有元素的value

  • 返回一个表单acceptCharset属性的值

  • 返回一个表单action属性的值

  • 返回表单中的enctype属性的值

  • 返回一个表单中元素的数量

  • 返回发送表单数据的方法

  • 返回一个表单的name

  • 返回一个表单target属性的值

  • 重置表单

  • 提交表单

Frame/IFrame 对象

  • 对iframe排版

  • 改变一个包含在iframe中的文档的背景颜色

  • 返回一个iframe中的frameborder属性的值

  • 删除iframe的frameborder

  • 改变iframe的高度和宽度

  • 返回一个iframe中的longdesc属性的值

  • 返回一个iframe中的marginheight属性的值

  • 返回一个iframe中的marginwidth属性的值

  • 返回一个iframe中的name属性的值

  • 返回和设置一个iframe中的scrolling属性的值

  • 改变一个iframe的src

Image 对象

  • 对image排版

  • 返回image的替代文本

  • 给image加上border

  • 改变image的高度和宽度

  • 设置image的hspace和vspace属性

  • 返回image的longdesc属性的值

  • 创建一个链接指向一个低分辨率的image

  • 返回image的name

  • 改变image的src

  • 返回一个客户端图像映射的usemap的值

Event 对象

  • 哪个鼠标键被点击了?

  • 被按下的键盘键的keycode?

  • 鼠标的坐标?

  • 鼠标相对于屏幕的坐标?

  • shift键被按下了吗?

  • 哪个元素被按下了?

  • 哪个事件发生了?

Option 和 Select 对象

  • 禁用和启用下拉列表

  • 获得有下拉列表的表单的ID

  • 获得下拉列表的选项数量

  • 将下拉列表变成多行列表

  • 在下拉列表中选择多个选项

  • 弹出下拉列表中所有选项

  • 弹出下拉列表中被选中的选项的索引

  • 改变下拉列表中被选中的选项的文本

  • 删除下拉列表中的选项

Table, TableHeader, TableRow, TableData 对象

  • 改变表格边框的宽度

  • 改变表格的cellpadding和cellspacing

  • 指定表格的frame

  • 为表格指定规则

  • 一个行的innerHTML

  • 一个单元格的innerHTML

  • 为表格创建一个标题

  • 删除表格中的行

  • 添加表格中的行

  • 添加表格行中的单元格

  • 单元格内容水平对齐

  • 单元格内容垂直对齐

  • 对单个单元格的内容水平对齐

  • 对单个单元格的内容垂直对齐

  • 改变单元格的内容

  • 改变单元格横跨的列数(colspan属性)


vue3实现一个区域多选的选择框。

用户需求是可以选择服务区域,本来想找个省市县级联的一个选择框就好了,但是又要求多选,而且是用户自己给出区域,无奈写一个,特记录下,顺便帮助后来者。


实现效果


效果展示


实现思路

  1. 使用一个div将添加区域给放起来,display设置为none,当点击添加时将这个div的display设置为block,实现添加区域的隐藏和显示
  2. 下拉框值改变时去改变选中索引(provinceIndex)这个变量,实现citybox中显示的城市内容的改变
  3. 点击城市内容时触发选中/取消选中 方法,其实为同一个方法,通过判断当前点击元素的class(class中包含is-selected则是已经选中的)来分辨是选中还是取消选中
  4. 在选中方法里将选中的对象添加到一个存放选中内容的列表(citys)中,并给点击元素的class添加上is-selected类,如果是取消选中则会在在citys列表做一个筛选,将取消的内容给去除
  5. 清空方法则是将citys列表清空,并且将有is-selected类的class设置为正常


实现代码

  • template部分
<template>
    <div class="form-item">
        <label for="city" class="form-label">服务区域</label>
        
        <span>
            <span style="background-color: rgb(245,247,249);margin-right: 5px;" v-for="item in citys" :key="item">{{
                item.name }}</span>
            <span @click="ClickAddCity" style="color: #0bbfbc;">点击添加</span>
        </span>

        <!-- 显示/隐藏部分 -->
        <div ref="citysDom" class="citysbox">
            <div class="citysbox-top">
           
                <div class="top-left">
                    <label for="city" class="form-label1">省份:</label>
                    <select required id="city" name="city" class="form-input form-input-select"
                        style="width: auto;color: #303030;" v-model="provinceIndex">
                        <option v-for="(item, index) in Provinces" :key="index" :value="index">
                        {{ item.name}}                        </option>
                    </select>
                </div>
                
                <div class="top-right">
                    <button type="button" class="btn-close" @click="ClickAddCity">关闭</button>
                    <button type="button" class="btn-confirm" @click="ClickReastBtn">清空</button>
                    <button type="button" class="btn-confirm" @click="ClickAddCity">确认</button>
                </div>
            </div>
            <!-- 城市内容部分 -->
            <div class="citysbox-body">
                <div v-for="item in Provinces[provinceIndex].city" :key="403 Forbidden"
                :class="citys.includes(item) ? 'box-item is-selected' : 'box-item'"
                @click="SelectChange(item, $event)">
                    {{ item.name }}</div>
            </div>
            
        </div>
    </div></template>


  • script部分
<script setup>
	import { ref } from 'vue';
	// 省市信息
	const Provinces = [
	    {
	        "id": 24,
	        "name": "北京市",
	        "city": [
	            {
	                "id": 268,
	                "name": "东城区",
	                "province": 24
	            },
	            {
	                "id": 269,
	                "name": "西城区",
	                "province": 24
	            }
	        ]
	
	    },
	    {
	        "id": 9,
	        "name": "福建省",
	        "city": [
	            {
	                "id": 109,
	                "name": "福州市",
	                "province": 9
	            },
	            {
	                "id": 110,
	                "name": "厦门市",
	                "province": 9
	            },
	            {
	                "id": 116,
	                "name": "龙岩市",
	                "province": 9
	            }
	        ]
	    }
	]
	// 添加服务区域相关
	var citysDom = ref() // dom对象
	var provinceIndex = ref(0) // 当前选择获取值
	var citys = ref([]) // 已选择城市
	
	// 点击添加时显示地址选择div
	function ClickAddCity() {
	    if (citysDom.value.style.display !== 'block')
	        citysDom.value.style.display = 'block';
	    else citysDom.value.style.display = 'none';
	}
	
	// 选中地址
	function SelectChange(item, e) {
	    
	    let domClass = e.currentTarget.getAttribute("class")
	    // 判断item的class区别两种情况,一种是点击未选中的item选中 , 一种是点击已选中的取消选中
	    if (domClass == "box-item") {
	        e.currentTarget.className = "box-item is-selected"
	        // 将选中对象添加到citys列表中
	        citys.value.push(item)
	    } else {
	        e.currentTarget.className = "box-item"
	        // 将取消选中对象从citys列表中去除
	        citys.value = citys.value.filter(val => val.id != 403 Forbidden)
	    }
	    console.log('citys:', citys.value)
	}
	
	// 清空地址区域
	function ClickReastBtn() {
	    citys.value = []
	    let items = document.getElementsByClassName("is-selected");
	    console.log('length',items.length);
	    console.log('items:',items, typeof(items));
	    // 清空已选择的样式
	    Array.prototype.forEach.call(items, function (item) {
	        item.className = "box-item" 
	    });
	}
	</script>


  • css部分
<style scoped>
	.form-item {
	    margin-right: 24px;
	    margin-bottom: 24px;
	}
	
	.form-label {
	    height: 14px;
	    font-size: 14px;
	    color: #39475A;
	    letter-spacing: 0;
	    text-align: right;
	    line-height: 14px;
	    font-weight: 400;
	    margin-right: 12px;
	}
	.citysbox {
	    width: 700px;
	    max-width: 750px;
	    min-width: 360px;
	    padding: 10px;
	    min-height: 100px;
	    display: none;
	    position: absolute;
	    background: rgb(245, 247, 249);
	    border-radius: 10px;
	}
	
	.citysbox-top{
	    display: flex;
	    flex-direction: row;
	    justify-content: space-between;
	}
	.citysbox-body {
	    display: flex;
	    flex-direction: row;
	    flex-wrap: wrap;
	}
	
	.box-item {
	    margin: 10px 10px 0 0;
	    border: rgb(197, 208, 223) solid 1px;
	    border-radius: 4px;
	    padding: 3px;
	}
	
	.is-selected {
	    border: rgb(11, 192, 188) solid 1px;
	    color: rgb(11, 192, 188);
	}</style>


总结

以上

内容已经说得比较详细了,特此记录





如对你有所帮助的话可以帮我点个赞,感谢