Airtest-Selenium实操小课②:刷B站视频
1. 前言
上一课我们讲到用Airtest-Selenium爬取网站上我们需要的信息数据,还没看的同学可以戳这里看看~
那么今天的推文,我们就来说说看,怎么实现看b站、刷b站的日常操作,包括点击暂停,发弹幕,点赞,收藏等操作,仅供大家参考学习~
2.需求分析和准备
整体的需求大致可以分为以下步骤:
- 打开chrome浏览器
- 打开百度网页
- 搜索“哔哩哔哩”
- 点击进入“哔哩哔哩”官网
- 搜索关键词“Airtest酱”
- 点击进入“Airtest酱”首页,随机点击播放视频
- 并对视频点击暂停,发弹幕,点赞,收藏
在写脚本之前,我们需要准备好社区版AirtestIDE(目前最新版为1.2.16),设置好chrome.exe地址和对应的driver;并且确保我们的chrome浏览器版本不是太高以及selenium是4.0以下即可(这些兼容问题我们都会在后续的版本修复)。
3. 脚本实现与运行效果
3.1 脚本运行效果
我们在编写这次代码的时候,我们主要是使用了页面元素定位的方式去进行操作交互的,除此之外还实现了保存cookie、读取cookie的一个操作。大家在日常使用也会发现,在首次通过脚本开启的chrome网页界面是无cookie的,那么我们在进行一些任务之前是需要先登录后才能进行下一步操作的,可以通过首次登录时读取cookie数据保存到本地,往后每次运行只需要读取本地的cookie文件就可以轻松登录啦~
先来看下我们整体的运行效果:
Airtest-selenium实现自动化刷b站
3.2 完整代码分享
这里也附上完整的示例代码给大家参考,有需要的同学可以自取学习哦:
# -*- encoding=utf8 -*-
from airtest.core.api import *
# 引入selenium的webdriver模块
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
import threading
import time
import random
import json#保存以及调用cookie的线程
class UtilFunc():def cookie_is_exist_(self, cook_name='_'): # 检查txt文件是否存在if os.path.exists(f'{cook_name}cookies.txt'):return Truereturn Falsedef cookie_save_(self, driver, cook_name='_'): #保存cookie到txt文件中以便下次读取# 获取当前页面的所有cookiecookies = driver.get_cookies()# 将cookie转换为JSON字符串cookies_json = json.dumps(cookies)# 保存cookie到txt文件with open(f'{cook_name}cookies.txt', 'w') as file:file.write(cookies_json)print(f"保存cookies:{cookies}")def cookie_set_(self, driver, cook_name='_'): #读取cookie文件并给当前网站设置已存cookie# 从txt文件读取JSON_cookie数据with open(f'{cook_name}cookies.txt', 'r', encoding='gbk') as file:json_data = file.read()# 将JSON数据转换为列表data_list = json.loads(json_data)for cookie in data_list:driver.add_cookie(cookie)print("设置cookie")# 创建一个实例,代码运行到这里,会打开一个chrome浏览器
driver = WebChrome()
isLogin = False #存储登录状态值,False为未登录,True为已登录#打开chrome浏览器并打开视频播放
def start_selenium():driver.implicitly_wait(20)driver.get("https://www.baidu.com/")# 输入搜索关键词并提交搜索search_box = driver.find_element_by_name('wd')search_box.send_keys('哔哩哔哩')search_box.submit()try:# 查找搜索结果中文本为 "哔哩哔哩" 的元素并点击results = driver.find_elements_by_xpath('//div[@id="content_left"]//span[contains(text(), "哔哩哔哩")]')if results:results[0].click()print("点击了哔哩哔哩搜索结果")except Exception as e:element = driver.find_element_by_xpath("//div[@id='content_left']/div[@id='1']/div[@class='c-container']/div[1]/h3[@class='c-title t t tts-title']/a")element.click()driver.switch_to_new_tab() # 切换界面util_cookie = UtilFunc()if util_cookie.cookie_is_exist_("Airtest酱登录"): # 存在cookie文件,设置cookieutil_cookie.cookie_set_(driver, "Airtest酱登录")# 输入搜索关键词并提交搜索search_box = driver.find_element_by_class_name('nav-search-input')search_box.send_keys('Airtest酱')# 模拟发送Enter键search_box.send_keys(Keys.ENTER)sleep(5)driver.switch_to_new_tab() # 切换界面results_ = driver.find_elements_by_xpath('//div[@class="bili-video-card__info--right"]//span[contains(text(),"Airtest酱")]')if results_:results_[0].click()driver.switch_to_new_tab() # 切换界面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()driver.switch_to_new_tab() # 切换界面# 获取所有视频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_new_tab() # 切换界面#登录
def is_login():"""线程检测登录弹窗"""def is_no_login(*args):global isLogin # 在线程内修改外部常量的值no_login_tip = Truewhile True:element = driver.find_elements_by_css_selector('.bili-mini-content-wp')if len(element) > 0:if no_login_tip:print("未登录 请在五分钟内扫码")no_login_tip = Falseelse:print("未检测到登录弹窗")check_login_ele = driver.find_elements_by_css_selector('.bpx-player-dm-wrap')if not check_login_ele:isLogin = TrueUtilFunc().cookie_save_(driver, "Airtest酱登录")print("保存cookie")breaklog_text_array = [element.text for element in check_login_ele] # 使用列表推导式简化代码if "请先登录或注册" in log_text_array:loginbtn = driver.find_elements_by_xpath("//div[@class='bili-header fixed-header']//div[@class='header-login-entry']")if loginbtn:loginbtn[0].click()isLogin = Falseprint("判断cookie文件是否存在,方便下次调用,设置后刷新页面")else:isLogin = TrueUtilFunc().cookie_save_(driver, "Airtest酱登录")print("保存cookie")breakthread = threading.Thread(target=is_no_login, args=("args",))thread.start()#暂停播放
def video_pause_and_play(check_btn=False):if isLogin: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].textsleep(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].textif start_time == end_time or check_btn:print("点击播放(暂停)按钮")paus_btn[0].click()except Exception as e:print(f"点击播放(暂停)出错{e}")#发送弹幕
def video_sms(sms_body="不错"):if isLogin:try:sms_input_edit = driver.find_element_by_xpath("//input[@class='bpx-player-dm-input']")sms_input_edit.send_keys(sms_body)# 模拟发送Enter键sms_input_edit.send_keys(Keys.ENTER)except Exception as e:print(f"发弹幕出错{e}")print(f"发送弹幕:{sms_body}")#点赞
def video_love():if isLogin: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("已经点赞")returnsms_input_edit[0].click()except Exception as e:print(f"点赞出错{e}")#收藏
def video_collect():if isLogin: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("已经收藏")returncolle_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) # 随机收藏# 滚动到指定元素处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:element = WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.XPATH, selector)))return elementexcept 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() # 开启浏览器找到视频播放is_login() # 检测是否出现登录弹窗# 等待元素出现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) # 随机生成等待时间,单位为秒time.sleep(wait_time) # 等待随机的时间video_sms(item) # 评论# 点赞和收藏视频for action in [video_love, video_collect]:action()sleep(3)else:print("登录超时")
3.2 重要知识点
1)切换新页面并打开新的标签页
driver.switch_to_new_tab()
**2)将随机的元素 random_element对象的“顶端”移动到与当前窗口的“顶部”**对齐。
driver.execute_script("arguments[0].scrollIntoView(true);", random_element)
3) 从非空序列中随机选取一个数据并返回,该序列可以是list、tuple、str、set**。**
random.choice()
4) 通过实例化threading.Thread类创建线程,target:在线程中调用的对象,可以为函数或者方法;args为target对象的参数。
start():开启线程,如果线程是通过继承threading.Thread子类的方法定义的,则调用该类中的run()方法;start()只能调用一次,否则报RuntimeError。
threading.Thread(target=is_no_login, args=("args",))
thread.start()
5) 使用expected_conditions模块(在使用时通常重命名为EC模块)去判断特定元素是否存在于页面DOM树中,如果是,则返回该元素(单个元素),否则就报错。
EC.presence_of_element_located((By.XPATH, selector))
4. 注意事项与小结
4.1 相关教程
- 如何使用Airtest-selenium进行web端的页面元素交互
- 如何设置chromedriver以及一些常见的web脚本问题
- 为什么AirtestIDE无法检索web控件?
4.2 课程小结
在本周的课程中,我们介绍了如何使用Airtest-selenium进行自动化刷B站视频的操作流程,也分享了Airtest-selenium比较常见的用法。但是,请大家注意,我们的分享仅供学习参考哦!我们分享的代码并不是永远适用的,因为网页的页面元素可能会不断更新。
同时,我们也非常欢迎同学们能够提供自己常用场景的代码,我们会积极分享相关的使用技巧。让我们一起努力,共同进步~
相关文章:
Airtest-Selenium实操小课②:刷B站视频
1. 前言 上一课我们讲到用Airtest-Selenium爬取网站上我们需要的信息数据,还没看的同学可以戳这里看看~ 那么今天的推文,我们就来说说看,怎么实现看b站、刷b站的日常操作,包括点击暂停,发弹幕,点赞&#…...
Linux chmod命令详解
Linux chmod(英文全拼:change mode)命令是控制用户对文件的权限的命令 Linux/Unix 的文件调用权限分为三级 : 文件所有者(Owner)、用户组(Group)、其它用户(Other Users)…...
求幸存数之和 - 华为OD统一考试
OD统一考试(C卷) 分值: 100分 题解: Java / Python / C++ 题目描述 给一个正整数列nums,一个跳数jump,及幸存数量left。运算过程为:从索引为0的位置开始向后跳,中间跳过 J 个数字,命中索引为 J+1 的数字,该数被敲出,并从该点起跳,以此类推,直到幸存left个数为止。…...
【QML COOK】- 008-自定义属性
前面介绍了用C定义QML类型,通常在使用Qt Quick开发项目时,C定义后端数据类型,前端则完全使用QML实现。而QML类型或Qt Quick中的类型时不免需要为对象增加一些属性,本篇就来介绍如何自定义属性。 1. 创建项目,并编辑Ma…...
前端页面优化做的工作
1.分析模块占用空间 new (require(webpack-bundle-analyzer).BundleAnalyzerPlugin)() 2.使用谷歌浏览器中的layers,看下有没有影响性能的模块,或者应该销毁没销毁的 3.由于我们页面中含有很大的序列帧动画,所以会导致页面性能低࿰…...
Spark六:Spark 底层执行原理SparkContext、DAG、TaskScheduler
Spark底层执行原理 学习Spark运行流程 学习链接:https://mp.weixin.qq.com/s/caCk3mM5iXy0FaXCLkDwYQ 一、Spark运行流程 流程: SparkContext向管理器注册并向资源管理器申请运行Executor资源管理器分配Executor,然后资源管理器启动Execut…...
关于鸿蒙的笔记整理
提示:有使用过 vue 或 react 的小伙伴更容易理解 知识点强调: ArkTS所有内容都不支持深层数据更新 UI渲染 文章目录 一、关于样式1 . 默认单位 vp2 . 写公共样式 二 、 加载图片三 、 自定义构建函数 Builder四、构建函数-BuilderParam 传递UI五 、 父子…...
【漏洞复现】先锋WEB燃气收费系统文件上传漏洞 1day
漏洞描述 /AjaxService/Upload.aspx 存在任意文件上传漏洞 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作…...
MYSQL篇--锁机制高频面试题
Mysql锁机制 1对mysql的锁有了解吗? 首先我们要知道,mysql的锁 其实是为了解决在并发事务时所导致的数据不一致问题的一种处理机制,也就是说 在事务的隔离级别实现中,就需要利用锁来解决幻读问题 然后我们可以聊到锁的分类 按锁…...
创建一个郭德纲相声GPTs
前言 在这篇文章中,我将分享如何利用ChatGPT 4.0辅助论文写作的技巧,并根据网上的资料和最新的研究补充更多好用的咒语技巧。 GPT4的官方售价是每月20美元,很多人并不是天天用GPT,只是偶尔用一下。 如果调用官方的GPT4接口&…...
靶机实战(10):OSCP备考之VulnHub Tre 1
靶机官网:Tre: 1[1] 实战思路: 一、主机发现二、端口发现(服务、组件、版本)三、漏洞发现(获取权限) 8082端口/HTTP服务 组件漏洞URL漏洞(目录、文件)80端口/HTTP服务 组件漏洞URL漏…...
在windows11系统上利用docker搭建linux记录
我的windows11系统上,之前已经安装好了window版本的docker,没有安装的小伙伴需要去安装一下。 下面直接记录安装linux的步骤: 一、创建linux容器 1、拉取镜像 docker pull ubuntu 2、查看镜像 docker images 3、创建容器 docker run --…...
swift对接环信sdk
准备 熟练objective-c语言 有一台mac电脑,并安装了xcode 和 cocoapods 内容篇幅较长,需要内心平和耐心看下去,务必戒躁. 学习目的 手把手教大家如何在iOS应用中集成环信IM 明确表示,内容一定全面,没有任何丢失,只要沉得住气,耐得下心,3小时即可搞定. 若经常阅读文档以及语…...
单片机中的PWM(脉宽调制)的工作原理以及它在电机控制中的应用。
目录 工作原理 在电机控制中的应用 脉宽调制(PWM)是一种在单片机中常用的控制技术,它通过调整信号的脉冲宽度来控制输出信号的平均电平。PWM常用于模拟输出一个可调电平的数字信号,用于控制电机速度、亮度、电压等。 工作原理 …...
css 怎么绘制一个带圆角的渐变色的边框
1,可以写两个样式最外面的div设置一个渐变的背景色。里面的元素使用纯色。但是宽高要比外面元素的小。可以利用里面的元素设置padding这样挡住部分渐变色。漏出来的渐变色就像边框一样。 <div class"cover-wrapper"> <div class"item-cover…...
Kotlin DSL C++项目引入OpenCV异常处理
现象 kotlin DSL(build.rgadle.kts)项目引入openCV sdk 编译提示Plugin [id: com.android.application, version: 8.2.1...错误 Plugin [id: com.android.application, version: 8.2.1, apply: false] was not found in any of the following sources:* Try: > Run with -…...
【微服务】 Spring cold、Kubernetes、Service mesh
目录 Spring Cloud # 什么是微服务?谈谈你对微服务的理解? # 什么是Spring Cloud? # springcloud中的组件有那些? # 具体说说SpringCloud主要项目? # Spring Cloud 和dubbo区别? # 服务注册和发现是什么意思?S…...
【scala】编译build报错 “xxx is not an enclosing class“
private[sources] val creationTimeMs: Long {val session SparkSession.getActiveSession.orElse(SparkSession.getDefaultSession)require(session.isDefined)private[xxx]是访问权限控制在xxxx包的意思。 解决办法: 把[sources]删掉,或者改成和包名…...
vue3+ts+vite项目从0 搭建,配置安装router/pinia/element-plus/scss等
一、安装vite环境 官网:https://cn.vitejs.dev/guide/why.html npm init vite1.选择vue 2.选择typescipt 3.创建成功 默认项目结构如下 4.安装项目依赖 npm install 5.启动项目 npm run dev二。安装配置scss 1.运行安装scss npm install -D sass sass-loa…...
华为OD机试 - 矩阵匹配(Java JS Python C)
题目描述 从一个 N * M(N ≤ M)的矩阵中选出 N 个数,任意两个数字不能在同一行或同一列,求选出来的 N 个数中第 K 大的数字的最小值是多少。 输入描述 输入矩阵要求:1 ≤ K ≤ N ≤ M ≤ 150 输入格式: N M K N*M矩阵 输出描述 N*M 的矩阵中可以选出 M! / N! 种组合数…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
