selenium的作用域及解决登录验证问题

一、selenium的作用域切换

selenium在处理元素时遇见新窗口、网页嵌套网页、网页的原生弹窗,无法进行直接处理作用域里元素的内容,需要通过切换作用域来处理此类问题。

selenium三种作用域切换:

①、window窗口切换

②、iframe切换

③、alert弹窗切换

1、window窗口切换

以百度为例,在原百度的网页上,点击超链接后会打开一个新的网页,这个时候如果需要定位新的网页上的元素,就需要切换作用域了。

 

切换作用域实现方案:

使用driver.window_handles,可以获取全部网页的索引,并且将索引存放于一个数组中,因此可以通过数组取值的方式实现切换网页作用域:driver.switch_to.window(driver.window_handles[-1])

切换作用域后,原网页上就无法进行元素定位了,可以通过数组下标取值的方式,将作用域切换为原网页:driver.switch_to.window(driver.window_handles[0])

 代码实现:

from selenium import webdriver

#打开浏览器
driver = webdriver.Chrome("chromedriver.exe")
driver.maximize_window()
#打开网页
driver.get("https://www.baidu.com/")


driver.find_element_by_link_text("hao123").click()      #会跳转一个新的hao123的窗口,此时就无法操作原百度网页的窗口了,因此需要切换作用域
#获取所有网页的索引:driver.window_handles
# print(driver.window_handles)    #打印出来的值是一个数组:['37554D9C36A0A691571C87C250434881', '860CA08A7CEEB72959449FCB3B75D146'],因此可以通过数组取值的方式实现切换网页作用域
driver.switch_to.window(driver.window_handles[-1])   #把driver切换到最新弹出来的窗口
print(driver.title)    #获取当前网页的标题
driver.find_element_by_xpath('//*[@id="search"]/form/div[2]/input').send_keys("博客园")

2、iframe切换

在某些后台管理系统中,网页中嵌套小网页,这种情况是没有办法直接处理小网页的,大网页的内容是可以直接处理的

1.2.1、识别小网页

怎么查看哪些页面是嵌套小网页的:iframe通常在大网页中是以iframe标签存在的,标签里面也会有html的标签。我们可以通过源代码或者右键空白区域去判断是否存在【重新加载框架选项】:

①源代码查看标签判断:定位元素后,去代码前后找是否有iframe标签,且里面还有html标签

②右键空白区域查看是否存在【重新加载框架选项】判断:

1.2.2、切换作用域

先找到iframe标签的id值,然后定位元素,再使用driver.switch_to.frame()方法切换。相同的道理,切换作用域后,原网页就无法进行元素的定位,可将作用域切换回原网页:driver.switch_to.default_content()

代码实现:

from selenium import webdriver

driver = webdriver.Chrome("chromedriver.exe")
driver.maximize_window()
driver.get("https://passport2.eastmoney.com/pub/login")

#作用域从大网页切换到小网页(不同版本的selenium有以下两种写法)
driver.switch_to.frame(driver.find_element_by_id('frame_login') )     #frame_login为frame标签的id值
driver.switch_to.frame("frame_login")
#输入框的xpath://*[@id="txt_mobile"]
driver.find_element_by_xpath('//*[@id="txt_mobile"]').send_keys("110")

#把作用域从小网页切换到大网页(不同版本的selenium有以下两种写法)
driver.switch_to.default_content()
driver.switch_to.parent_frame()      

#/html/body/div[1]/div/div/h1
e = driver.find_element_by_xpath('/html/body/div[1]/div/div/h1')
print(e.text)     #能成功打印,说明小网页切换大网页成功了

3、alert弹窗切换

alert窗口就是js提示框,它是浏览器原声的弹窗,不属于web界面,所以,在有这个提示框的作用下,我们是无法继续web操作的,必须先处理掉js弹窗,才可以继续。

Alert类提供了四个方法来处理弹窗:

driver.switch_to.alert.accept()     # 确定操作
driver.switch_to.alert.dismiss()     # 取消操作
driver.switch_to.alert.send_keys("")     # alert弹框输入文本
driver.switch_to.alert.text()        # 获取alert的文本内容

代码实现:

from selenium import webdriver
import time
#打开浏览器,获得浏览器句柄
driver = webdriver.Chrome("chromedriver.exe")
driver.maximize_window()
driver.get("http://localhost:8080/selenium/selenium6.html")

#xpath:/html/body/a
driver.find_element_by_xpath('/html/body/a').click()

time.sleep(10)   #等待10s查看弹窗关闭效果

driver.switch_to.alert.accept()     # 确定操作
driver.switch_to.alert.dismiss()     # 取消操作
driver.switch_to.alert.send_keys("")     # alert弹框输入文本
driver.switch_to.alert.text()        # 获取alert的文本内容

二、登录验证

在做自动化测试时,有些图形化的验证码很复杂,验证码的作用是为了防止自动化工具,可以有以下几种方式去处理它:

  • 万能码
  • 深度学习
  • 使用cookie绕过登录

服务器验证用户身份的方式有两种:第一种是使用cookie和session的方式;第二种是使用token的方式。

第一种验证方式下,我们可以使用已经登录账号的cookie,来伪造账号已经登录了

2.1、cookie理解

  • 比如用户登录了某个网站后,再次刷新这个页面去请求服务器,如果没有相关机制的话,服务器是不知道这个请求是否还是刷新之前登录的用户发出来的。此时,为了维持用户的登录状态,即为了使服务器能够识别页面刷新之后的请求,就可以使用cookie机制。
  • 用户A第一次请求服务器后,服务器会自动生成一个暗号,并将这个暗号的一部分返回给用户A,用户A将其以cookie的方式存起来,下次再次访问的时候,会自动把cookie带上,服务器拿到cookie后将其与自己的进行比对,识别出是用户A(以此类推,不同的用户有不同的暗号),服务器通过这种方式以此来识别各个用户。
  • 为什么要这样做:请求时用的是http协议,http协议有一个特点就是:无状态,即服务器在每次请求时,他不知道谁是谁,为了解决这个问题,就诞生了cookie和session机制。在服务器上以session的形式存在,用户端以cookie的形式存在。
  • 例如用户A已经登录,在服务器上对应的session就会是登录状态,用户A再次请求,服务器就不会让用户A再进行以此登录操作了。所以,cookie绕过登录其实是登录状态保持,而不是真的不需要登录
  • cookie只是一个暗号,所有的登录记录都是存在session里

2.2 使用cookie绕过登录的实现

①、第一步:获取已经登录的cookie

from selenium import webdriver
import time

driver = webdriver.Chrome("chromedriver.exe")
driver.maximize_window()
driver.get("https://www.bilibili.com/")


#第一步:获取已经登录的cookie(手工抓取)
time.sleep(60)   #等待的时间用于手动登录
print(driver.get_cookies())

②、第二步:手动添加已经登录的cookie(在添加之前需要将原有的cookie删掉)

由于Selenium每次启动的浏览器是一个隔离的环境,不能直接使用本地已经保存的Cookies值,我们需要通过driver的add_cookie()方法手动添加Cookies
#第二步:手动添加已经登录的cookie(在添加之前需要将原有的cookie删掉)
driver.delete_all_cookies()
#下面是刚才获取的cookie,是以数组形式存在的,可遍历添加cookie
cookies = [{'domain': '.bilibili.com', 'expiry': 1695112960, 'httpOnly': False, 'name': 'sid', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '63frdsq6'}, {'domain': '.bilibili.com', 'expiry': 1695112960, 'httpOnly': False, 'name': 'DedeUserID__ckMd5', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': 'f4485c3372ed2570'}, {'domain': '.bilibili.com', 'expiry': 1695112960, 'httpOnly': False, 'name': 'DedeUserID', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '330209683'}, {'domain': '.bilibili.com', 'expiry': 1695112960, 'httpOnly': True, 'name': 'SESSDATA', 'path': '/', 'sameSite': 'Lax', 'secure': True, 'value': '1e95ca9e%2C1695112959%2Cecfeb%2A32'}, {'domain': '.bilibili.com', 'expiry': 1714120928, 'httpOnly': False, 'name': 'buvid_fp', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '8f569ef970983d50acfdb16927dd8d30'}, {'domain': '.bilibili.com', 'expiry': 1711096928, 'httpOnly': False, 'name': 'home_feed_column', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '5'}, {'domain': '.bilibili.com', 'expiry': 1711096927, 'httpOnly': False, 'name': 'header_theme_version', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': 'undefined'}, {'domain': '.bilibili.com', 'expiry': 1711096926, 
'httpOnly': False, 'name': 'buvid3', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '4282D8E7-631E-6994-116E-F4F45047C2C625602infoc'}, {'domain': '.bilibili.com', 'expiry': 1711096926, 'httpOnly': 
False, 'name': '_uuid', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '349AD710A-96E6-10C51-2A79-59411089EA1F526855infoc'}, {'domain': '.bilibili.com', 'expiry': 1695112960, 'httpOnly': False, 'name': 'bili_jct', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '186fb75ecff9463115a99723f07ca618'}, {'domain': '.bilibili.com', 'expiry': 1711096926, 'httpOnly': False, 'name': 'i-wanna-go-back', 
'path': '/', 'sameSite111': 'Lax', 'secure': False, 'value': '-1'}, {'domain': '.bilibili.com', 'httpOnly': False, 'name': 'b_lsid', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '11F1095B3_1870DA1E67B'}, {'domain': '.bilibili.com', 'expiry': 1711096926, 'httpOnly': False, 'name': 'b_ut', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '7'}, {'domain': '.bilibili.com', 'expiry': 1711096926, 'httpOnly': False, 'name': 'b_nut', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '1679560925'}, {'domain': '.bilibili.com', 'expiry': 1714120928, 'httpOnly': False, 'name': 'buvid4', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '21AF5084-1D17-E537-4D50-A58D04BC650A27080-023032316-cJA8FXQvRy7Izno/Qr2scs+wGicZ9uvk3uoERMAYhhTaajD9Va+nvA%3D%3D'}, {'domain': '.bilibili.com', 'httpOnly': False, 'name': 'innersign', 'path': '/', 'sameSite': 'Lax', 'secure': False, 'value': '0'}]
for cookie in cookies:
    driver.add_cookie(cookie)

③、第三步:刷新网页

#刷新网页
driver.refresh() 

 

posted @ 2023-03-27 17:28  一个名  阅读(785)  评论(0编辑  收藏  举报