高效Selenium测试技巧:轻松控制已开启的浏览器

此文章来源于项目官方公众号:“AirtestProject”
版权声明:允许转载,但转载必须保留原链接;请勿用作商业或者非法用途

一、前言

在日常做Selenium测试的时候,总是遇到网页需要登录的情况,上次我们在做Selenium专题的时候,有讲过一个自动刷B站的案例,里面涉及到了登录的情况,详细推文点击这里,很多同学也提出了疑问,是否可以通过执行当前我设置好并登录好的网页去进行测试?那么我们今天就一起来探讨一些,如何连接已经打开的浏览器,并进行自动化测试。

二、控制现有浏览器的步骤解析

我们这边以Chrome浏览器为例,我们这里采用的是Chrome DevTools协议,他们为客户提供了检查和调试Chrome浏览器的便利功能。

具体步骤如下:

1、在控制台内打开Chrome浏览器的文件夹

2、在命令行中输入命令:

chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\temp"

对于-remote-debugging-port参数,这里可以自由选择一个未被占用的端口号进行指定,后续在初始化Selenium连接的时候会用到该端口号。

至于--user-data-dir标志,它用于指定创建新Chrome用户数据文件夹的路径。这样做可以确保Chrome在一个新的、独立的配置文件中启动,从而避免对您的默认配置文件造成任何干扰。

3、执行完上述命令后,会生成打开一个全新的浏览器,可以在该浏览器上面进行初始化,新的用户数据也将会存在刚刚填入--user-data-dir参数的文件夹下面。

4、在进行好浏览器初始化后,在脚本中输入下述代码进行初始化,连接已开启的浏览器:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome(chrome_options=chrome_options)

做完这一步之后,就可以直接在已打开的浏览器上执行脚本或编写脚本啦。

注意:

1、该浏览器不小心关闭后,需要再次执行第二个步骤重新打开Chrome浏览器噢。一般登录状态也会随之保留的。

2、Airtest-selenium切换新网页作用域时,使用driver.switch_to_new_tab()会出现报错:'WebDriver' object has no attribute 'switch_to_window',只需要将切换新网页作用域语句改为:driver.switch_to.window(driver.window_handles[-1])即可。

三、代码案例

通过上述所讲的接管已开启浏览器的方式,我们将之前刷B站的代码重新修改一下,去掉了登录并存储cookie的方法,直接通过连接我们已打开登录好账号的浏览器,执行一系列的刷B站操作,如搜索、点击播放、发送弹幕等。

参考代码:

# 引入selenium的webdriver模块和其他必要的库
from airtest.core.api import *
from airtest_selenium.proxy import WebChrome
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
import threading
import time
import random
import json

# 设置Chrome选项,连接到已打开的Chrome浏览器
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver.implicitly_wait(20)

# 连接到已打开的Chrome浏览器
driver = webdriver.Chrome(options=chrome_options)

print(driver.title)

#打开chrome浏览器并打开视频播放
def start_selenium():
    # 输入搜索关键词并提交搜索
    search_box = driver.find_element(By.CLASS_NAME,'nav-search-input')
    search_box.send_keys('Airtest酱')
    
    driver.switch_to.window(driver.window_handles[-1])  # 切换界面
    sleep(3)

    #点击进入“Airtest酱”主页
    driver.find_element(By.XPATH,"//*[@id=\"i_cecream\"]/div/div[2]/div[2]/div/div/div/div[2]/div/div/div/div/div/div/h2/a").click()
    
    # 再次切换到新打开的标签页并刷新页面
    driver.switch_to.window(driver.window_handles[-1]) 
    driver.refresh()
       
    sleep(2)
    # 查找特定视频元素
    video_ele = driver.find_element(By.XPATH,"//div[@title='14天Airtest自动化测试小白课程']")

    # 滚动到该视频元素位置并点击
    driver.execute_script("arguments[0].scrollIntoView(true);", video_ele)
    sleep(5)
    video_ele.click()

    # 获取所有视频列表
    video_list = driver.find_elements(By.XPATH,"//ul[@class='row video-list clearfix']//a[@class='title']")

    # 随机选择一个视频并点击播放
    random_element = random.choice(video_list)
    random_element.click()

    # 切换到新打开的视频页面
    driver.switch_to.window(driver.window_handles[-1])

    # 暂停或播放视频
    random_element.click()  # 随机播放一个视频
    driver.switch_to.window(driver.window_handles[-1])  # 切换界面


#暂停播放
def video_pause_and_play(check_btn=False):
    
    try:
        # 查找播放/暂停按钮
        paus_btn = driver.find_elements(By.XPATH,
            "//*[@id=\"bilibili-player\"]//div[@class='bpx-player-ctrl-btn bpx-player-ctrl-play']")
        if paus_btn[0]:
            # 获取初始时间
            detection_time1 = driver.find_elements(By.XPATH,
                '//*[@class="bpx-player-control-bottom-left"]//div[@class="bpx-player-ctrl-time-label"]')
            start_time = detection_time1[0].text
            sleep(5)

            # 时间戳检测是否在播放
            detection_time2 = driver.find_elements(By.XPATH,
                '//*[@class="bpx-player-control-bottom-left"]//div[@class="bpx-player-ctrl-time-label"]')
            end_time = detection_time2[0].text
            
            # 如果时间没变或check_btn为True,则点击播放/暂停按钮
            if start_time == end_time or check_btn:
                print("点击播放(暂停)按钮")
                paus_btn[0].click()
    except Exception as e:
        print(f"点击播放(暂停)出错{e}")

#发送弹幕
def video_sms(sms_body="不错"):
    try:
        # 查找弹幕输入框
        sms_input_edit = driver.find_element(By.XPATH,"//input[@class='bpx-player-dm-input']")
        # 输入弹幕内容并发送
        sms_input_edit.send_keys(sms_body)
        sms_input_edit.send_keys(Keys.ENTER)
    except Exception as e:
        print(f"发弹幕出错{e}")
    print(f"发送弹幕:{sms_body}")

# 点赞视频
def video_love():
    
    print("点赞")
    try:
        # 查找点赞按钮
        sms_input_edit = driver.find_elements(By.XPATH,
            "//div[@class='toolbar-left-item-wrap']//div[@class='video-like video-toolbar-left-item']")
        if not sms_input_edit:
            print("已经点赞")
            return
        # 点击点赞按钮
        sms_input_edit[0].click()
    except Exception as e:
        print(f"点赞出错{e}")

# 收藏视频
def video_collect():

    print("收藏")
    try:
        # 查找收藏按钮
        colle_btn = driver.find_elements(By.XPATH,
            "//div[@class='toolbar-left-item-wrap']//div[@class='video-fav video-toolbar-left-item']")
        if not colle_btn:
            print("已经收藏")
            return
        # 点击收藏按钮
        colle_btn[0].click()
        sleep(2)
        # 获取收藏夹列表
        list_coll = driver.find_elements(By.XPATH,"//div[@class='group-list']//ul/li/label")

        # 随机选择一个收藏夹
        random_element = random.choice(list_coll)
        
        # 滚动到选中的收藏夹元素位置
        random_element = random.choice(list_coll)  # 随机收藏
        # 滚动到指定元素处
        driver.execute_script("arguments[0].scrollIntoView(true);", random_element)
        sleep(2)
        random_element.click()  # 随机收藏一个
        
        sleep(2)
        # 点击确认收藏按钮
        driver.find_element(By.XPATH,"//div/button[@class='btn submit-move']").click()
        
    except Exception as e:
        print(f"收藏出错{e}")

def wait_for_element(driver, selector, timeout=60 * 5):
    try:
        # 使用WebDriverWait等待元素出现
        element = WebDriverWait(driver, timeout).until(
            EC.presence_of_element_located((By.XPATH, selector))
        )
    except Exception:
        print("元素未出现")
        return None

# 定义用于检测登录状态的头像元素选择器

#头像元素初始化
selem = "//div[@class='bili-header fixed-header']//*[contains(@class, 'header-avatar-wrap--container mini-avatar--init')]"

if __name__ == "__main__":
    # 启动浏览器并打开视频
    start_selenium()

    # 等待元素出现
    element = wait_for_element(driver, selem)
    if element:
        print("检测到已经登录")

        # 执行暂停和播放操作
        for _ in range(2):
            video_pause_and_play()
            sleep(3)
        # 刷新页面
        driver.refresh()

        # 发送多条随机弹幕
        sms_list = ["感觉不错,收藏了", "666,这么强", "自动化还得看airtest", "干货呀", "麦克阿瑟直呼内行"]
        for item in sms_list:
            wait_time = random.randint(5, 10)  # 随机等待5-10秒
            time.sleep(wait_time)
            video_sms(item)  # 发送弹幕

        # 点赞和收藏视频
        for action in [video_love, video_collect]:
            action()
            sleep(3)
    else:
        print("登录超时")

四、小结

本周我们一起探讨了如何让selenium连接已开启的浏览器,通过Chrome DevTools协议,创建新的浏览器缓存,在该浏览器上提前做好对应的设置以及登录好对应的账号,就可以通过端口号可以连接到对应的浏览器上。大家也可以通过这个方式,随时在已开启的浏览器上进行调试,同时,我们也非常欢迎同学们能够提供自己在常用场景实现的代码。

如果大家在使用过程中有一些新的使用方式或者遇到了问题,又或者有任何想要深入了解的知识点,欢迎在官方交流群(526033840)里告诉我们或者提交issue。


AirtestIDE下载:airtest.netease.com/
Airtest 教程官网:airtest.doc.io.netease.com/
搭建企业私有云服务:airlab.163.com/b2b

官方答疑 Q 群:526033840