一、前言
在日常做Selenium测试的时候,总是遇到网页需要登录的情况,上次我们在做Selenium专题的时候,有讲过一个自动刷B站的案例,里面涉及到了登录的情况,详细推文点击这里,很多同学也提出了疑问,是否可以通过执行当前我设置好并登录好的网页去进行测试?那么我们今天就一起来探讨一些,如何连接已经打开的浏览器,并进行自动化测试。二、控制现有浏览器的步骤解析
我们这边以Chrome浏览器为例,我们这里采用的是Chrome DevTools协议,他们为客户提供了检查和调试Chrome浏览器的便利功能。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。