python代码学习——元素操作之浏览器操作、等待、窗口切换

浏览器操作

  • 打开一个会话 diver = webdriver.Chrome()
  • 访问网址 diver.get("www.baidu.com")
  • 全屏——窗口最大化:diver.maximize_window()
  • 设置窗口大小:diver.set_window_size(1440,900)
  • 关闭浏览器: diver.quit()
  • 他会做三件事:关闭chromdiver进程;关闭浏览器和恢复一些数据环境
  • 回退:diver.back()
  • 前进:diver.forward()
  • 刷新:diver.refresh()
  • 获取窗口标题:title= diver.title
  • 获取窗口的url:url = diver.current_url
  • 获取窗口的句柄:handle = diver.current_window_handle
  • 代码示例:
from selenium import webdriver
#打开一个会话
diver = webdriver.Chrome()
#全屏
diver.maximize_window()
#访问百度链接
diver.get("https://www.baidu.com")
# diver.find_elements_by_xpath("")
#百度登录
diver.get("https://www.csdn.net/")
#回退
diver.back()
#前进
diver.forward()
#刷新
diver.refresh()
#获取标题
title= diver.title
#获取当前窗口的utl
url = diver.current_url
#获取当前窗口的句柄
handle = diver.current_window_handle
print(title,url,handle)
# 设置窗口大小
diver.set_window_size(1440,900)
#关闭会话
diver.quit()

等待

  • 以下三种等待方式time可以分别和显性等待或者全局等待可以一起用,但是全局等待和显性等待不能一起使用,否则可能会出现bug
  • 什么时候用等待:只要在页面的操作有引起页面的变化,要进行下一步操作的时候必须要等到元素课件,就必须用等待

time.sleep

  • 导入time模块,使用time.sleep即可,代码如下
diver.get("https://www.baidu.com")
diver.find_element_by_xpath('//div[@id="u1"]//a[@name="tj_login"]').click()
time.sleep(2)
diver.find_element_by_xpath('//p[@class="tang-pass-footerBarULogin pass-link"]').click()
time.sleep(3)

智能等待方式

  • 全局等待:设置一个超时时长,如果加载时间超过10s,就直接报超时,如果在10s内加载完成,就去进行下一步的操作
  • 如果超时还没有找到元素,就会抛出NoSunchElementException:找不到元素
  • 全局等待方式,全局生效,只要设置之后,其之后的代码通过find_element都会有全局等待的效果
  • 全局等待放置的位置,一般会将其放在driver的初始化之后

隐性等待——全局等待时间

  • 方式:diver.implicitly_wait(10)#等待10s
  • 代码示例:
from selenium import webdriver
#打开一个会话
diver = webdriver.Chrome()
#全局等待方式
diver.implicitly_wait(10)#等待10s
#全屏
diver.maximize_window()
#访问百度链接
diver.get("https://www.baidu.com")
diver.find_element_by_xpath('//div[@id="u1"]//a[@name="tj_login"]').click()
diver.find_element_by_xpath('//p[@class="tang-pass-footerBarULogin pass-link"]').click()
diver.quit()#关闭会话

显性等待——等待被设置的元素可见/存在/点击

  • 明确的等待到某个条件满足后,再去进行下一步的操作
  • 程序每隔XX秒看一下,如果条件成立,则执行下一步,否则继续等到,直到超过设置的最长时间抛出异常
  • 显性等待如果超过设置时间还是找不到元素,就会抛出TimeoutExcption的异常
  • 显性等待方式后可以跟click,send_keys的操作,但是不会有提示信息
  • 局部生效,只对某个元素生效
  • 需要类和模块结合使用,需要导入相关的类:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
  • 类:WebDriverWait 用法:WebDriverWait(diver,等待时长,轮询周期).until(条件)/until_not(条件)。until等到 条件成立;until_not等到条件不成立;轮询周期,默认0.5s
  • 模块:expected_conditions
  • 元素存在:presence_of_element_located
  • 元素可见:visibility_of_element_located
  • 元素可点击:element_to_be_clickable
  • alert弹框呈现:alert_is_present
  • 新的窗口打开:new_window_is_opened
  • iframe的可用并且可切换:frame_to_be_available_and_switch_to_it
  • 元素可以被选择:element_selection_state_to_be
  • 元素应该被选中:element_to_be_selected
  • 元素不可见:invisibility_of_element_located
  • 应该显示多少个窗口:number_of_windows_to_be
  • 文本的内容确认:text_to_be_present_in_element
  • 文本的values应该是:text_to_be_present_in_element_value
  • 标题应该为:title_is
  • 标题包含:title_contains
  • url的变化:url_changes
  • url包含:url_contains
  • url应该是:url_matches
  • 代码示例:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
#打开一个会话
diver = webdriver.Chrome()
#全屏
diver.maximize_window()

#访问百度链接
diver.get("https://www.baidu.com")
ele_loc_1 = (By.XPATH,'//div[@id="u1"]//a[@name="tj_login"]')
#传入定位方式和信息,定位方式有ID、Xpath,class等,信息是值
WebDriverWait(diver,10).until(EC.visibility_of_element_located(ele_loc_1))
#等待10s,知道元素元素可见
diver.find_element_by_xpath('//div[@id="u1"]//a[@name="tj_login"]').click()#可见后点击
ele_loc_2 = (By.XPATH,'//p[@class="tang-pass-footerBarULogin pass-link"]')#元素元组
WebDriverWait(diver,10).until(EC.visibility_of_element_located(ele_loc_2))#等待元素可见
diver.find_element_by_xpath('//p[@class="tang-pass-footerBarULogin pass-link"]').click()#可见后点击
ele_loc_3 = (By.ID,"TANGRAM__PSP_11__userName")#元素元组
WebDriverWait(diver,10).until(EC.visibility_of_element_located(ele_loc_3))#等待元素可见
diver.find_element_by_id("TANGRAM__PSP_11__userName").send_keys("叶子")#可见后输入信息
time.sleep(3)
diver.quit()#关闭会话

三种等待方式的优缺点

time.sleep 随时可以等待,但是不灵活,比较死板。数据动态加载过程中用这种方式不稳定
全局等待:智能等待,可以根据元素出现,代码命令完成来智能控制时间;但是有一些场景不能处理,例如窗口切换(新窗口。alert。ifram),等待元素可见、可用也等待不了
隐性等待:智能等待,可以根据元素的可见。可用、窗口切换、出现等当时来智能等待,但是会出现返回成功但是还不能操作的情况,建议和time结合使用

全局等待和显性等待的区别

  • 1.找不到元素之后,抛出的异常不一样,全局抛出的异常是找不到元素,显性等待抛出的异常是超时
  • 2.全局等待全局生效,显性等待只对特定的元素生效
  • 3.等待条件的区别:全局等待只能等待元素存在,显性等待可等待的条件很多,例如元素可见,点击,存在等

切换

网页窗口切换

  • 进行web自动化的时候,有时候会出现打开一个新的窗口,在当前窗口查找另外一个窗口的元素是找不到的,这个时候需要用到窗口切换
  • 点击超链接的时候,什么时候回打开新的窗口?——当超链接的元素中有属性:target="_blank"的时候,会打开新的窗口
  • 窗口切换的前提是:1.触发新窗口出现,2.得知新窗口的是谁?(一般用句柄)3.得到窗口的句柄
  • diver.window_handles获取窗口所有的句柄,存在返回值,需要变量能接收;以列表的形式返回,最新打开的窗口句柄为列表中的最后一个值
  • 获得窗口的句柄并不是一成不变的,而是浏览器随机分配的;但是窗口的句柄是唯一的,不会重复,但是其并不固定
  • 窗口切换:diver.switch_to.window("切换窗口的句柄")
  • 代码示例:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
#打开一个会话
diver = webdriver.Chrome()
#全屏
diver.maximize_window()
diver.implicitly_wait(30)

try:
    # 访问百度链接
    diver.get("https://www.baidu.com")
    WebDriverWait(diver, 20).until(EC.visibility_of_element_located((By.ID, "kw")))
    # 等待文本框可见
    diver.find_element_by_id("kw").send_keys("百度贴吧")  # 输入内容
    WebDriverWait(diver, 20).until(EC.visibility_of_element_located((By.ID, "su")))
    # 等待百度一下可见
    diver.find_element_by_id("su").click()  # 点击
    WebDriverWait(diver, 20).until(
        EC.visibility_of_element_located((By.XPATH, '//a[text()="吧 - "]')))
    diver.find_element_by_xpath('//a[text()="吧 - "]').click()  # 点击
    time.sleep(3)
    handles_list = diver.window_handles
    print(handles_list)# 获取所有窗口的handle
    diver.switch_to.window(handles_list[-1])  # 切换到最后一个窗口——切换到全新的html页面
    # 等待百度贴吧可见
    WebDriverWait(diver, 20).until(
        EC.visibility_of_element_located((
            By.ID,"tab_picture")))  # 等待图片按钮可见
    diver.find_element_by_id("tab_picture").click()
    time.sleep(3)
    # 退出
    diver.quit()
except Exception as e:
    # 退出
    diver.quit()
    raise e
  • 优化:使用新窗口出现替换time.sleep
  • 代码示例:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
#打开一个会话
diver = webdriver.Chrome()
#全屏
diver.maximize_window()
diver.implicitly_wait(30)

try:
    # 访问百度链接
    diver.get("https://www.baidu.com")
    # 窗口切换
    WebDriverWait(diver, 20).until(EC.visibility_of_element_located((By.ID, "kw")))
    # 等待文本框可见
    diver.find_element_by_id("kw").send_keys("百度贴吧")  # 输入内容
    WebDriverWait(diver, 20).until(EC.visibility_of_element_located((By.ID, "su")))
    # 等待百度一下可见
    diver.find_element_by_id("su").click()  # 点击
    WebDriverWait(diver, 20).until(
        EC.visibility_of_element_located((By.XPATH, '//a[text()="吧 - "]')))
    handles_list = diver.window_handles#使用此种方式,要将获取句柄列表放在打开新窗口之前
    print(handles_list)
    diver.find_element_by_xpath('//a[text()="吧 - "]').click()  # 点击
    WebDriverWait(diver,20).until(EC.new_window_is_opened(handles_list))
    handles_list_new = diver.window_handles
    print(handles_list_new)  # 获取所有窗口的handle
    diver.switch_to.window(handles_list_new[-1])  # 切换到最后一个窗口——切换到全新的html页面
    # 等待百度贴吧可见
    WebDriverWait(diver, 20).until(
        EC.visibility_of_element_located((
            By.ID,"tab_picture")))  # 等待图片按钮可见
    diver.find_element_by_id("tab_picture").click()
    time.sleep(3)
    # 退出
    diver.quit()
except Exception as e:
    # 退出
    diver.quit()
    raise e
  • 如果浏览器同时打开了多个窗口,应该怎么解决?
  • 可以通过循环遍历句柄,通过窗口的标题或者地址来判断是否是目标窗口,然后切换到目标窗口中
  • 获取网页的标题driver.title
  • 确认步骤:
    • 1.获取全部的句柄,然后for循环遍历
    • 2.判断driver.title是否符合目标值,如果是break退出
    • 3.否则就切换到目标窗口,切换代码:driver.switch_to.window(handle)

alert切换

  • 遇到这种弹框的时候,不需要先关闭,然后才能去做后续操作
  • alert切换:diver.switch_to.alert
  • 关闭:使用ALert来关闭,
  • Alert可以做以下操作:1。获取文本:属性.text 2.accept(),代表确定、3.dismiss(),代表取消,4.send_keys()输入内容
  • 等待新的alert弹框出现:alert_is_present() 这种方式有返回值,可以使用一个变量来接收,接收之后可以不切换窗口,如果不接收,就需要使用窗口切换
    • chrome浏览器暂时不支持send_keys的输入方式,可以使用火狐浏览器
  • 代码示例:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
#打开一个浏览器,开启浏览器会话。
diver = webdriver.Chrome()
#全屏
diver.maximize_window()
diver.implicitly_wait(30)
driver.get('D:\\Pychram-Workspace\\python12_web\\myHtml.html')
#点击
driver.find_element_by_id("btn").click()
#等待alert弹框出现
alert = WebDriverWait(driver,10).until(EC.alert_is_present())
#切换
#alert = driver.switch_to.alert
#alert是一个类。1、获取文本提示内容 .text;2、accept(),代表确定、dismiss(),代表取消  3、send_keys()
print(alert.text)
alert.accept()#接受,关闭

iframe切换

  • iframe的标志:在F12使用鼠标选中元素的时候,在xpath输入框的上方存在ifram标识的,就是ifram弹框
  • 也可以在搜索框中输入//iframe来确定有没有iframe弹框
    在这里插入图片描述
  • 什么时候切换ifram?
  • 当要操作的元素在ifram中时,才需要切换jfram,判断的依据为元素信息在ifram之后,例如下图:
    在这里插入图片描述
  • ifram弹框在F12中定位的时候会没有问题,但是在使用selenium运行的时候,会找不到这个元素,因此需要先切换在进行登录
  • 思路:
  • 1、确认你要操作的元素,是否在iframe当中。如果元素在iframa当中,则切换;
  • 2、先找到这个iframe.等待iframe可见;
  • 3、切换frame,根据ifram下标、名字和webelement,使用webelement的时候要用driver先找到元素
  • 4、切换成完成之后,目前就是以iframe当中的html为主html
  • 等待两种方式,第一种:time.sleep(0.5);第二种,使用EC中的方法,等待ifram可见且可使用
  • 代码示例,第一种等待ifram课件后切换,使用ifram切换方法进行切换
  • 切换到iframe的代码: driver.switch_to.frame(driver.find_element(By.XPATH,"iframe的定位"))
  • 切换到父级的iframe:driver.switch_to.parent_frame()
  • 回到默认网页:driver.switch_to.default_content()
    • 使用场景:切换到iframe中之后,如果还需要用到外面的元素,就需要切换至默认界面
import time
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
#打开一个浏览器,开启了一个浏览器会话
diver=webdriver.Chrome()#打开谷歌浏览器
diver.implicitly_wait(10)
try:
    #打开链接
    diver.get('https://ke.qq.com/')
    #放大窗口
    diver.maximize_window()
    time.sleep(0.5)
    #等待登录可见
    WebDriverWait(diver,20).until(
        EC.visibility_of_element_located((By.XPATH,'//div[@id="js-mod-entry-index"]//a')))
    #点击登录
    diver.find_element_by_xpath('//div[@id="js-mod-entry-index"]//a').click()
    #iframe的xpath
    elc_loc='//div[@class="login-qq-iframe-wrap"]//iframe'
    #等待iframe可见
    WebDriverWait(diver,20,1).until(EC.visibility_of_all_elements_located((By.XPATH,elc_loc)))
    #iframe切换
    #iframe切换有三种方式,1.名字;2.webelement;3.下标
    #名字直接输入,下标是int,但是不推荐,因为可能有变化;webelement需要先用driver寻找
    #webelement切换iframe   switch_to.frame
    diver.switch_to.frame(diver.find_element_by_xpath(elc_loc))
    #登录
    diver.find_element_by_id("switcher_plogin").click()
    diver.find_element_by_id("u").send_keys("XXX")
    diver.find_element_by_id("p").send_keys('XXX')
    diver.find_element_by_id("login_button").click()
    time.sleep(10)
    diver.quit()  # 关闭
except Exception as e:
    diver.quit()
    raise e
  • 第二种方式,直接使用webdriverwait中的ifram方法,用此方法不需要切换,等待的时候自动切换了,代码如下:
import time
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
try:
    #打开链接
    diver.get('https://ke.qq.com/')
    #放大窗口
    diver.maximize_window()
    time.sleep(0.5)
    #等待登录可见
    WebDriverWait(diver,20).until(
        EC.visibility_of_element_located((By.XPATH,'//div[@id="js-mod-entry-index"]//a')))
    #点击登录
    diver.find_element_by_xpath('//div[@id="js-mod-entry-index"]//a').click()
    #iframe的xpath
    elc_loc='//div[@class="login-qq-iframe-wrap"]//iframe'
    #直接等待切换,注意,webelement方式要传元组,将通过什么方式查找也传进去
    #这种方式等待之后直接切换
    WebDriverWait(diver,20,1).until(
        EC.frame_to_be_available_and_switch_to_it((By.XPATH,elc_loc)))
    time.sleep(0.5)
    #登录
    diver.find_element_by_id("switcher_plogin").click()
    diver.find_element_by_id("u").send_keys("XXX")
    diver.find_element_by_id("p").send_keys('XXX')
    diver.find_element_by_id("login_button").click()
    time.sleep(10)
    diver.quit()  # 关闭
except Exception as e:
    diver.quit()
    raise e
  • 切换至默认页面点击元素
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("https://qzone.qq.com/")
driver.maximize_window()
iframe_xpath  =(By.ID,"login_frame")#iframe定位
WebDriverWait(driver,20).until(EC.visibility_of_all_elements_located(iframe_xpath))#等待iframe存在
iframe = driver.find_element(*iframe_xpath)#找到iframe
driver.switch_to.frame(iframe)#切换idrame
driver.find_element(By.ID,'switcher_plogin').click()#点击账号登录
driver.find_element(By.ID,"u").send_keys("935913608")#输入账号
driver.find_element(By.ID,"p").send_keys("123456")#输入密码
driver.find_element(By.ID,"login_button").click()#点击登录
time.sleep(5)
driver.switch_to.default_content()#回到默认页面
driver.find_element(By.XPATH,"//i[@class='ui_icon icon_iphone']").click()#点击iphone的按钮,在默认界面
driver.close()

如果元素定位不到,会有哪些原因?

  • 1.检查元素定位表达式是否有误,通过F12搜索验证
  • 2.确认是否需要加等待
  • 3.检查元素是否在iframe中,如果是,就需要切换iframe
  • 4.确认元素是否在新的窗口中,如果是,就需要去切换窗口
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值