Airtest-Selenium实操小课

news2024/11/20 20:25:51

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文件就可以轻松登录啦~

先来看下我们整体的运行效果:

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 True
        return False

    def cookie_save_(self, driver, cook_name='_'):     #保存cookie到txt文件中以便下次读取
        # 获取当前页面的所有cookie
        cookies = 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文件,设置cookie
        util_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 = True
        while True:
            element = driver.find_elements_by_css_selector('.bili-mini-content-wp')
            if len(element) > 0:
                if no_login_tip:
                    print("未登录 请在五分钟内扫码")
                    no_login_tip = False
            else:
                print("未检测到登录弹窗")
                check_login_ele = driver.find_elements_by_css_selector('.bpx-player-dm-wrap')
                if not check_login_ele:
                    isLogin = True
                    UtilFunc().cookie_save_(driver, "Airtest酱登录")
                    print("保存cookie")
                    break
                log_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 = False
                    print("判断cookie文件是否存在,方便下次调用,设置后刷新页面")
                else:
                    isLogin = True
                    UtilFunc().cookie_save_(driver, "Airtest酱登录")
                    print("保存cookie")
                    break

    thread = 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].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
                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="不错"):
    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("已经点赞")
                return
            sms_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("已经收藏")
                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)  # 随机收藏
            # 滚动到指定元素处
            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 element
    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()  # 开启浏览器找到视频播放
    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))

Python接口自动化测试零基础入门到精通(2024最新版)

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1375179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python基础(二十四、JSON和pyecharts)

文章目录 一、JSON1.JSON介绍2.JSON格式数据转化3.示例 二、pyecharts1.安装pyecharts包2.查看官方示例 三、开发示例 一、JSON 1.JSON介绍 JSON是一种轻量级的数据交互格式,采用完全独立于编程语言的文本格式来存储和表示数据(就是字符串)…

使用MySQL的过程中,有没有遇到过count()比较慢的情况?

count(*)的实现方式 MyISAM引擎把一个表的总行数存在了磁盘上,执行count(*)的时候直接返回这个数,效率很高; InnoDB引擎执行count(*)的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。 上述说明是在没有…

03.C++内存管理笔记

1、C/C内存分布 ①内存分那么多区的原因:不同的数据,有不同的存储需求,各区域满足了不同的需求。 ②存放: 临时变量等临时用的变量:栈区; 动态申请的变量:堆区; 全局变量和静态变…

[渗透测试学习] Surveillance -HackTheBox

文章目录 信息搜集getshell提权信息搜集 nmap扫描端口 nmap -sV -sC -v -p- --min-rate 1000 10.10.11.245扫出来两个端口,其中80端口有http服务并且重定向到surveillance.htb 那么我们添加下域名然后访问80端口,发现是企业网站尝试扫描子域名和目录无果后,用Wappalyzer插…

紫光展锐5G扬帆出海 | Blade系列勇当拉美5G先锋

5G对拉丁美洲(简称“拉美”)绝大多数消费者来说还是一个新鲜技术。GSMA报告显示,过去五年,拉美运营商在移动网络方面的资本开支大部分用于部署4G网络。但在5G网络方面拉美也在积极大力投入中,紧跟全球5G发展大潮&#…

「 典型安全漏洞系列 」02.SQL注入详解

引言:SQL注入是一个老生常谈且又非常重要的漏洞,导致许多热点的数据泄露事件。尽管学习起来相对简单,但它可能用于某些高危漏洞的利用。这使得它成为初学者的兴趣点,甚至对于更有经验的用户来说,SQL注入也是基本知识。…

R语言下载安装及VScode配置

文章目录 1. R 下载和安装1.1 下载1.2 安装 2. VSCODE 配置2.1 安装R拓展2.2 安装R语言辅助功能包2.3 DEBUG 1. R 下载和安装 1.1 下载 网址:https://www.r-project.org/ 选择一个镜像地址下载 选择对应的版本 一般选择base即可 1.2 安装 下载安装包后按提示安装…

Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin

Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin 手指在上面的图上移动,“剪切”出上面图中以手指触点为中心的图(半径图),然后在下面的ImageView显示。 impor…

java实现AES256对称加解密工具类

一、引入依赖包 引入相关依赖包 <dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.70</version> </dependency> <!--lombok用于简化实体类开发--> <dependency&g…

MySQL-索引回顾

索引是面试高频问答题&#xff0c;参考百度/CSDN/尚硅谷/黑马程序员/阿里云开发者社区&#xff0c;决定将索引知识回顾一下&#xff0c;忘记时&#xff0c;点开即可&#xff0c;时刻保持更新&#xff0c;事不宜迟&#xff0c;即刻享用。 索引概述 索引&#xff08;index&#…

2000-2021年全国各省环境相关指标数据(890+指标)

2000-2021年全国各省环境相关指标数据&#xff08;890指标&#xff09; 1、指标时间&#xff1a;2000-2021年 2、范围&#xff1a;31省市 3、来源&#xff1a;2001-2022年环境统计年鉴 4、指标&#xff1a;工业废水排放总量、工业废水排放达标量、工业废水处理量、化学需氧…

离散数学3

补变元 解释&#xff1a;它是以反^作为一组一组的&#xff0c;因此&#xff0c;对于P反^Q来说&#xff0c;P是一组&#xff0c;Q是一组&#xff0c;又有以下&#xff1a;对缺少变元的项要补齐&#xff0c;P缺少Q&#xff0c;Q缺少P。因此&#xff0c;补齐。 用分配律展开 解释&…

基于Vue组合式API的实用工具集

简介 今天,给大家分享一个很实用的工具库 VueUse,它是基于 Vue Composition Api,也就是组合式API。支持在Vue2和Vue3项目中进行使用,据说是目前世界上Star最高的同类型库之一。 图片 官方地址:https://vueuse.org/ 中文地址:https://www.vueusejs.com/ github:https…

深度解析Cron表达式:精确控制任务调度的艺术

深度解析Cron表达式&#xff1a;精确控制任务调度的艺术 希望我们都可以满怀期待的路过每一个转角 去遇见 那个属于自己故事的开始 去追寻那个最真实的自己 去放下 去拿起 安然&#xff0c;自得&#xff0c;不受世俗牵绊… 导言 在计算机科学领域&#xff0c;任务调度是一项关…

RabbitMQ(六)消息的持久化

目录 一、简介1.1 定义1.2 消息丢失的场景 二、交换机的持久化方式一&#xff1a;直接 new方式二&#xff1a;channel.exchangeDeclare()方式三&#xff1a;ExchangeBuilder【推荐】 三、队列的持久化方式一&#xff1a;直接 new方式二&#xff1a;channel.queueDeclare()方式三…

【算法Hot100系列】组合总和

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

回首24考研历程,那些无法忘却的收获

文章目录 毅力与坚持&#x1f44d;知识的力量&#x1f9d0;心态的历练&#x1f913;友谊与互助( •̀ ω •́ )y未来的启示(●◡●) 在这个充满希望与挑战的时刻&#xff0c;我想与你们分享一段关于2023这一年特别的经历——考研之路。这段旅程既有磨砺的痛楚&#xff0c;也有…

基础篇_快速入门(Java简介,安装JDK,cmd命令行运行Java文件产生乱码问题的解决方式,IDE工具,实用工具)

文章目录 一. Java 简介1. JVM2. JRE3. JDK 二. 安装 JDK1. 下载和安装2. 配置 Path3. 配置 JAVA_HOME&#xff08;选讲&#xff09;优化 三. 入门案例1. 第一行代码1) jshell2) 代码解读总结 3) 为何要分成对象与方法 2. 第一份源码1) 源码结构2) 编写 java 源代码3) 编译 jav…

Python基础知识:整理10 异常相关知识

1 异常的捕获 1.1 基础写法 """基本语法&#xff1a;try:可能发生错误的代码except:如果出现异常&#xff0c;将执行的代码""" try:fr open("D:/abc.txt", "r", encoding"utf-8") except:print("出现异常…

1小时收到几百份简历

最近一直在招人&#xff0c;一些情况我也在星球群里也说了&#xff0c;目前找工作的人确实很多&#xff0c;只要发布职位&#xff0c;几百号人来投简历。 因为我本身带学员&#xff0c;之前我说我在boss上基本上都会回&#xff0c;但后来我让求职者总结自己的优势点时候发现&am…