web自动化

元素定位

XPATH选择器

什么是xpath?

XPath即为XML路径语言,它是一种用来(标准通用标记语言的子集)在 HTML\XML 文档中查找信息的语言。

W3School官方文档:http://www.w3school.com.cn/xpath/index.asp

什么是XML?

XML 指可扩展标记语言(EXtensible Markup Language)

XML 是一种标记语言,很类似 HTML

XML 的设计宗旨是传输数据,而非显示数据

image-20230424100332874

节点的概念

每个XML/HTML的标签我们都称之为节点

image-20230424100411769

路径表达式

基本语法

表达式 示例 描述表达式
nodename html/body/div 选取此节点的所有子节点(不推荐)
/ /html/head 从根节点选取
// //input 相对路径
. //input/. 选取当前节点
.. //input/.. 选取当前节点的父节点
@ //*[@type="text"] 选取属性

查找某个特定的节点

/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()❤️] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang=’eng’] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

选择未知节点

通配符 描述
* 匹配任何元素节点。
@* 匹配任何属性节点。
node() 匹配任何类型的节点。

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素。
//* 选取文档中的所有元素。
//title[@*] 选取所有带有属性的 title 元素。

选取若干路径

路径表达式 结果
//book/title | //book/price 选取 book 元素的所有 title 和 price 元素。
//title | //price 选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

补充

更多操作路径表达式 结果
//*[text()=“xxx”] 文本内容是xxx的元素
//*[starts-with(@attribute,’xxx’)] 属性以xxx开头的元素
//*[contains(@attribute,’xxxxx’)] 属性中含有xxx的元素
//*[@attribute1=value1 and @attribute2=value2] 同时有两个属性值的元素
//*[contains(@class,"myans_check")]/label
//*[contains(@class,"right_check")]/label

XPath的运算符(了解)

image-20230424162828595

CSS选择器

通过id,class等定位元素

image-20230424162107803

通过元素之间的嵌套定位元素

image-20230424162208102

通过元素的属性定位元素

image-20230424162240305

通过父子关系定位元素

image-20230424162436105

通过元素状态定位元素

image-20230424162455433

其他

image-20230424162609920

定位实例

xpath选择器

通过节点名定位(http://www.ifeng.com/)
html						定位到html节点
html/head					定位到head节点
html/head/meta				定位好head中的所有meta节点
相对路径定位节点(http://www.ifeng.com/)
//title						使用相对路径定位到title节点
//meta						使用相对路径定位到所有meta节点
使用.和..定位本身和父节点(http://www.ifeng.com/)
/html/head/title/./..		使用.定位到title本身再使用..定位到title的父节点
/html/head/title/./../body	使用.定位到title本身再使用..定位到title的父节点,然后在定位到body子节点
通过@定位   格式 标签名[@属性名='属性值']
/meta[@name='author']		定位到所有的meta,再从中找到name=author的那一个
//div[@id]					定位到所有div标签,再过滤出有id属性的节点
通配符定位节点
//*							匹配所有节点
/*							匹配绝对路径最外层
//*[@*]						匹配所有有属性的节点
/html/node()/meta			匹配所有含有meta的节点

糗事百科练习xpath
//div[@id="content-left"]/div				定位到所有糗事帖子节点
//div[@id="content-left"]/div[1]			通过索引定位到第一个节点
//div[@id="content-left"]/div[last()]		通过last()索引定位到结果中的最后一个
//div[@id="content-left"]/div[last()-n]		通过last()-n索引定位到结果集中的倒数第n+1个
//div[@id="content-left"]/div[position()=n]	定位到结果集中第n个节点
//div[@id="content-left"]/div[position()<n]	定位到结果集中索引小于n的节点
//div[@id="content-left"]/div[position()>n] 定位到结果集中索引大于n的节点
//span[i=n]									定位到好笑计数等于n的节点
//span[i>n]									定位到好笑计数大于n的节点

//meta | //script | //link					使用多个xpath,所有xpath的结果都放到一个结果集中
//*[starts-with(@name,'rend')]				匹配以标签属性值以给定值开头的节点
//*[contains(@name,'end')]					匹配给定值在标签属性中的节点
//*[@content="noarchive" and @name="robots"]匹配同时符合两个属性值的节点


css选择器

.weixinBottom				通过class的值进行定位
#wx							通过id的值进行定位
div							通过标签进行定位

meta,link					匹配两种标签结果集
div a						匹配div标签中的所有后代a标签
div>a						匹配div后是一个a标签的节点
div+div						匹配div后面的同胞div节点

[id]						匹配所有含有id属性的标签
[id='wx']					匹配所有含有id并且值为wx的标签
[type="submit"]	
[class~="Login"]			定位标签属性class值中有独立Login的节点
[name|=msapplication]		定位标签属性name的值以msapplicatio开头的节点(该节点需为一个完整的单词)


[src^="http://"]			匹配scr属性以http://开头的节点
[src$="js"]					匹配src属性以js结尾的节点
[src*="ifengimg"]			匹配src属性中含有ifengimg的节点

img:only-child				匹配所有独生子女的img节点
body>div:nth-child(1)		匹配body的第n个div子节点
body>*:nth-last-child(1)	匹配body的最后一个子节点

:not(link)					查找不是link标签的节点

xpath helper

XPath Helper安装及使用

Selenium

API基础

浏览器驱动对象

1)库的导入

 from selenium import webdriver

2)创建浏览器对象

driver = webdriver.xxx()

使用dir(driver)查看方法

3)浏览器尺寸/位置相关操作

maximize_window() 最大化

get_window_size() 获取浏览器尺寸
set_window_size() 设置浏览器尺寸

get_window_position()		获取浏览器位置
set_window_position(x,y)		设置浏览器位置
注:显示器以左上角为(0,0),所有的位置操作都是相对于显示器左上角展开的位移操作,单位是像素。

4)浏览器的关闭操作

close()		关闭当前标签页
quit()		关闭浏览器

页面操作

url的格式:

形式 scheme://host[:port#]/path/…/[?query-string][#anchor]

scheme:协议(例如:http, https, ftp)

host:服务器的IP地址或者域名

port:服务器的端口(如果是走协议默认端口,80 or 443)

path:访问资源的路径

http://www.cnblogs.com/be-saber/p/4734951.html

query-string:参数,发送给http服务器的数据,参数使用&隔开

anchor:锚(跳转到网页的指定锚点位置)

https://detail.tmall.com/item.htm?id=545181862652

协议

HTTP

• 超文本传输协议

• 默认端口号:80

HTTPS

• HTTP + SSL(安全套接字层,)

• 默认端口号:443

DNS域名服务

image-20230426131720342

页面请求操作

driver.get(url) 请求某个url对应的响应

refresh() 刷新页面操作

back() 回退到之前的页面

forward() 前进到之后的页面

断言

获取断言信息的操作

current_url				获取当前访问页面url

title						获取当前浏览器标题

get_screenshot_as_png()	   保存图片

get_screenshot_as_file(file)	直接保存
		
page_source				网页源码

元素定位

定位方式分类

image-20230426132120187

元素操作

	1)点击和输入

		点击操作
			element.click()
		
		清空/输入操作(只能操作可以输入文本的元素)
			element.clear()				清空输入框
			element.send_keys(data)		输入数据
	
	2)提交操作
		element.submit()		

	3)获取元素信息

		获取文本内容(开闭标签之间的内容)
			element.text
		
		获取属性值(获取element元素的value属性的值)
			element.get_attribute(value)
		
		获取元素尺寸(了解)
			element.size
		
		获取元素是否可见(了解)
			element.is_dispalyed()

API高级

多标签页切换

1.多标签之间的切换
	场景:有的时候点击一个链接,新页面并非由当前页面跳转过去,而是新开一个页面打开,这种情况下,计算机需要识别多标签或窗口的情况。
	
	1)获取所有窗口的句柄

		handles = driver.window_handlers()
		调用该方法会得到一个列表,在selenium运行过程中的每一个窗口都有一个对应的值存放在里面。
        handle = driver.current_window_handle:
        该方法可用得到当前所处窗口的句柄

	2)通过窗口的句柄进入的窗口

		driver.switch_to_window(handles[n])
		
		driver.switch_to.window(handles[n])

示例:

def switch_windows(driver, url):
	# 新开一个窗口,通过执行new一个窗口
	driver.execute_script("window.open('{}')".format(url))
	# 获取当前窗口句柄集合(列表类型)
	handles = driver.window_handles
	for handle in handles:  # 切换窗口(切换到课程页面)
		if handle != driver.current_window_handle:
			handle_new = handle
			driver.close()
			driver.switch_to.window(handle_new)
			break

多表单切换

2.多表单切换
	在网页中,表单嵌套是很常见的情况,尤其是在登录的场景

	1)什么是多表单?
		实际上就是使用iframe/frame,引用了其他页面的链接,真正的页面数据并没有出现在当前源码中,但是在浏览器中我们看到,简单理解可以使页面中开了一个窗口显示另一个页面


	2)处理方法
		
		直接使用id值切换进表单
			driver.switch_to.frame(value)/driver.switch_to_frame(value)

		定位到表单元素,再切换进入
			el = driver.find_element_by_xxx(value)
			driver.switch_to.frame(el)	/driver.switch_to_frame(el)
            
		跳回最外层的页面
            driver.switch_to.default_content()
            
        跳回上层的页面
            driver.switch_to.parent_frame()

鼠标和键盘操作

手动测试时键盘的操作在selenium页有实现,关于鼠标的操作由ActionChains()类来提供,关于键盘的操作由Key()类来提供

导入动作链类,动作链可以储存鼠标的动作,并一起执行
from selenium.webdriver import ActionChains

ActionChains(driver)

执行ActionChains中储存的所有动作
perform()


鼠标右击
el = driver.find_element_by_xxx(value)
ActionChains(driver).context_click(el).perform()

双击操作
el = driver.find_element_by_xxx(value)
ActionChains(driver).double_click(el).perform()

鼠标悬停
el = driver.find_element_by_xxx(value)
ActionChains(driver).move_to_element(el).perform()

键盘操作
键盘操作使用的是Keys类,一般配合send_keys使用

导入
from selenium.webdriver.common.key import Key

常用键盘操作
send_keys(Keys.BACK_SPACE)  删除键(BackSpace)

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

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

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

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

send_keys(Keys.CONTROL,‘a’)  全选(Ctrl+A)

send_keys(Keys.CONTROL,‘c’)  复制(Ctrl+C)

send_keys(Keys.CONTROL,‘x’)  剪切(Ctrl+X)

send_keys(Keys.CONTROL,‘v’)  粘贴(Ctrl+V)

send_keys(Keys.F1)  键盘 F1
……
send_keys(Keys.F12)  键盘 F12

弹出框操作

进入到弹出框中
driver.switch_to.alert()
接收警告
accept()
解散警告
dismiss()
发送文本到警告框
send_keys(data)

下拉框操作

selenium关于下拉框的操作都交由Select类进行处理,一般获取到下拉框元素之后使用该类构建对象,调用对象的响应方法就能操作元素

导入Select类
from selenium.webdriver.support.select import Select

将定位到的下拉框元素传入Select类中
selobj = Select(element) 下拉框元素已经定位到


调用响应方法选择下拉框中的选项
select_by_index() 通过索引选择,index 索引从 0 开始
select_by_value() 通过值选择(option标签的一个属性值)
select_by_visible_text() 通过文本选择(下拉框的值)

调用响应方法选择下拉框中的选项
all_selected_options 查看所有已选
first_selected_option 查看第一个已选
is_multiple 查看是否是多选
options 查看选项元素列表

取消选择
deselect_by_index()
deselect_by_value()
deselect_by_visible_text()

调用JS

什么是JS?

JavaScript是世界上最流行的脚本语言,因为你在电脑、手机、平板上浏览的所有的网页,简单地说,JavaScript是一种运行在浏览器中的解释型的编程语言,用来给HTML网页增加动态功能。

JavaScript 是属于网络的脚本语言,被数百万计的网页用来改进设计、验证表单、检测浏览器、创建cookies,以及更多的应用。

为什么要执行js代码?

因为selenium鞭长莫及,没有操作滚动条的方法,而一般操作滚动条都是使用js实现的。

js = "window.scrllTo(x,y)"  #  x为水平拖动距离,y为垂直拖动举例
js = "var q=document.documentElement.scrollTop=n"  # n为从顶部往下移动滚动举例
driver.execute_script(js)  # 执行JS代码

举例:
js = "window.scrllTo(0,1000)"

浏览器等待

隐式等待

driver.implicitly_wait(n)

显式等待

WebDriverWait类是由WebDirver 提供的等待方法。在设置时间内,
默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置
时间检测不到则抛出异常。

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

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

固定等待

import sleep from time
sleep(10)

cookies操作

get_cookies()			获取所有cookies

get_cookie(key)		获取key对应的值

add_cookie(cookie_dict)	设置cookies

delete_cookie(name)	  删除指定名称的cookie

delete_all_cookies()		删除所有cookie

使用cookie可以实现多账户的免登录,实战可参考这里:selenium中get_cookies()和add_cookie()的用法 - 年轻人——001 - 博客园 (cnblogs.com)

API封装

封装开启关闭浏览器

封装定位操作

封装对元素的基本操作

unittest模块

基本概念

test fixture: 代表了用例执行前的准备工作和用例执行之后的清理工作。

test case: 测试用例,测试的最小单位,一般检查一组输入的响应(输出)是否符合预期。unittest模块提供了TestCase类来帮助我们创建测试用例;

test suite: 经常被翻译成”测试套件”,也有人称为”测试套”,是测试用例或测试套件的集合,一般用来把需要一起执行的用例组合到一起;

test runner: 用来执行测试用例并输出测试结果的组件。可以是图形界面或命令行界面;

基本用法

1.通过继承unittest.TestCase进行编写,继承unittest.TestCase的类会被框架识别为测试用例。

2.setUp和TearDown是用于事前和事后做相关处理动作的,就是前面说的Test Fixture,会在每个测试用例运行前后被框架自动调用

3.所有以test开头的方法会被框架自动识别为测试用例,并自动调用执行,不是以test开头的不会被调用

4.unittest.main()是最简单的测试执行方式

5.调用unittest.main()方法后,继承自unittest.TestCase类的类会被自动识别为测试用例并且被调用。

断言

断言是测试用例的核心,unittest使用assertEqual()来判断预期结果,用assertTrue()和assertFalse()来做是非判断

总结

image-20230601132256779

posted @ 2023-06-01 13:35  Lexie——01  阅读(14)  评论(0编辑  收藏  举报