Playwright之初体验

news2024/11/22 18:50:31

参考文件

官方文档:https://playwright.dev/docs/intro
GitHub链接:https://github.com/microsoft/playwright-python

Playwright简介

Playwright Test是专门为满足端到端测试的需求而创建的。Playwright支持所有现代搜索引擎,包括Chrome、WebKit和Firefox。在Windows、Linux和macOS上测试,使用Android和mobile Safari的Google Chrome原生移动模拟进行测试。

环境安装

安装python环境
Playwright安装
使用pip install playwright命令进行安装
在这里插入图片描述
使用playwright install命令进行各种工具包和依赖,有报错,我们先不管,继续往下走
在这里插入图片描述
安装pytest插件:pip install pytest-playwright
在这里插入图片描述

简单跑一个demo,发现报错了,我们换一种执行方式
在这里插入图片描述

我们使用pytest命令执行发现没有报错
在这里插入图片描述

Playwright的自带工具

Playwright codegen
我们在pycharm中使用终端,输入该命令,之后,就会启用被测浏览器,并且启用inspector记录操作的脚本
在这里插入图片描述

Playwright inspector
在这里插入图片描述
之后我们可以将inspector里面的代码复制到pycharm里面自己编辑了

当然,我们也可以针对某个浏览器的网址,比如说https://www.baidu.com/

在这里插入图片描述

回车之后,浏览器自动启动一个标签,以及一个inspector来记录操作代码
在这里插入图片描述

也可以固定浏览器某个窗口的大小进行操作

Playwright codegen --viewport-size=800,600 www.baidu.com
在这里插入图片描述

在这里插入图片描述

访问移动端手机浏览器,比如说苹果13

Playwright codegen --device=“iPhone 13” www.baidu.com

在这里插入图片描述

在这里插入图片描述

帮助我们自动记录和管理cookie信息

首先我们使用如下命令Playwright codegen --save-storage=auth.json work-be.test.mi.com/main-buildstore/home/address:8000
然后浏览器启动一个窗口
在这里插入图片描述

接下来我们自动输入密码,如下:
在这里插入图片描述
之后,我们把启动的浏览器关掉
接下来,我们再次使用如下命令再次回车
Playwright codegen --load-storage=auth.json work-be.test.mi.com/main-buildstore/home/address:8000
在这里插入图片描述

浏览器会再次启动一个新窗口,但是此窗口浏览器的地址我们可以看到是登录状态的
在这里插入图片描述
Trace Viewer是Playwright的另一个神器,顾名思义就是痕迹查看,也就是我们后期可以查看我们之前都操作了哪些地方

Playwright架构技术介绍

Playwright是由Puppeteer-https://puppeteer.bootcss.com/改造过来的,Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。Puppeteer 默认以 headless 模式运行,但是可以通过修改配置文件运行“有头”模式。再加上,Playwright官方没有给出架构图,所以我们可以参考Puppeteer的架构图来学习Playwright
首先我们可以通过Puppeteer来控制浏览器的,他是通过谷歌开发者协议,简称CDP,该协议是建立在WebSocket协议之上
这里的Brower其实是一个浏览器实例,一个浏览器可以包含很多个上下文,也就是包含很多Context,通俗来讲,就跟我们打开了一个谷歌浏览器,又开启了一个无痕模式浏览器一样,Brower的Context具有独立的Session,cookie&cache
一个Context可以包含很多个Page页面,一个Page是一个独立页面
一个Page可以包含很多个Frame,一个Frame可以理解为是一个框架,可以包含多个子框架
再往下就是ExecutionContext,它是javascript的执行环境,每一个Frame都有一个默认的javascript的执行环境
在Playwright中,这些概念也是一样的
在这里插入图片描述

第一个Playwright脚本

from playwright.sync_api import sync_playwright

def test_pla():
    with sync_playwright() as p:
        #实例化一个浏览器,使用谷歌为例
        #代码运行默认是无头模式运行,如果要看运行效果,可以加入参数headless
        browser = p.chromium.launch(headless=False)
        #实例化一个页面
        page = browser.new_page()
        #打开一个网站
        page.goto("https://www.bilibili.com")
        #打印网页标题
        print(page.title())
        #关闭浏览器
        browser.close()

运行之后:
在这里插入图片描述

Playwright浏览器控制

谷歌官方相关命令地址:https://peter.sh/experiments/chromium-command-line-switches/

from playwright.sync_api import sync_playwright

def test_pla():
    with sync_playwright() as p:
        #实例化一个浏览器,使用谷歌为例
        #代码运行默认是无头模式运行,如果要看运行效果,可以加入参数headless
        #--start-maximized表示窗口最大化,no_viewport表示的是默认窗口大小失效
        #slow_mo表示的是每一步操作,默认等待3s
        browser = p.chromium.launch(headless=False,args=["--start-maximized"],slow_mo=3000)
        #实例化一个页面
        page = browser.new_page(no_viewport=True)
        #打开一个网站
        page.goto("https://www.zhihu.com")
        #打印网页标题
        print(page.title())
        #点击开通机构号
        page.get_by_text("开通机构号").click()
        #后退
        page.go_back()
        #前进
        page.go_forward()
        #刷新
        page.reload()
        #关闭浏览器
        browser.close()

Playwright浏览器启动参数详解

executable_path——数据路径
channel——指定使用哪种浏览器
args——参数数组
ignore_default_args——忽略默认参数,慎用,使用不当,脚本无法执行
timeout——等待浏览器实例启动的最长时间,单位毫秒,一般是30s,设置为0,功能失效
headless——有头和无头模式运行的设置
traces_dir——数据报错路径
chromium_sandbox——是否启动谷歌沙盒浏览器
等等,基本所有参数都是launch()函数里面的,可以自行查看
在这里插入图片描述

Playwright xpath元素定位

XML Path Language

from playwright.sync_api import sync_playwright

def test_pla():
    with sync_playwright() as p:
        #实例化一个浏览器,使用谷歌为例
        #代码运行默认是无头模式运行,如果要看运行效果,可以加入参数headless
        #--start-maximized表示窗口最大化,no_viewport表示的是默认窗口大小失效
        #slow_mo表示的是每一步操作,默认等待3s
        browser = p.chromium.launch(headless=False,args=["--start-maximized"],slow_mo=3000)
        #实例化一个页面
        page = browser.new_page(no_viewport=True)
        #打开一个网站
        page.goto("https://www.baidu.com")
        """
        /:从根节点选取
        //:从非根节点选取
        *:任意节点选取
        @:根据属性筛选
        text():根据文本筛选
        and:关联属性或者链接文本
        []:可以防止下标/属性/链接文本
        .:选取当前节点
        ..:选取当前节点的父节点
        contains:包含
        """
        #使用单一属性定位,   点击百度首页设置按钮,使用text_content获取内容
        t_1 = page.locator("//span[@name='tj_settingicon']").text_content()
        print(t_1)
        #多属性定位
        t_2 = page.locator("//span[@id='s-usersetting-top' and @name='tj_settingicon']").text_content()
        print(t_2)
        #父节点定位
        t_3 = page.locator('//div[@id="u1"]/span').text_content()
        print(t_3)
        #通过下标进行定位,新闻这个按钮
        t_4 = page.locator('//div[@id="s-top-left"]/a[1]').text_content()
        print(t_4)
        #通过.和..来定位
        t_5= page.locator('//a[@name="tj_fanyi"]/div/../../../../../a[1]').text_content()
        print(t_5)
        #通过文本定位
        t_6 = page.locator('//a[text()="新闻"]').text_content()
        print(t_6)
        #通过模糊匹配定位
        t_7 = page.locator('//a[contains(text(),"hao")]').text_content()
        print(t_7)
        #关闭浏览器
        browser.close()

运行之后:
在这里插入图片描述

Playwright css定位

css定位方式有五种,分别是:
id选择器
class选择器
元素选择器
属性选择器
层级选择器

from playwright.sync_api import Playwright, sync_playwright, expect

playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False,slow_mo=2000)
page = browser.new_page()
page.goto("https://www.baidu.com/")

#id属性定位
page.locator("#kw").fill("playwright")
page.locator("#su").click()

page.go_back()
page.locator(".s_ipt").fill("playwright")
page.locator("#su").click()

page.go_back()
page.locator("input#kw").fill("playwright")
page.locator("#su").click()

page.go_back()
page.locator("div>form>span>input.s_ipt").fill("playwright")  #层级关系
page.locator("#su").click()

browser.close()

Playwright特有定位方式

"""
特有元素定位方法
locator.get_by_alt_text(text,**kwargs),  alt属性
locator.get_by_label(text,**kwargs),label属性
locator.get_by_placeholder(text,**kwargs),placeholder属性
locator.get_by_role(role,**kwargs),role属性
locator.get_by_text(text,**kwargs)
locator.get_by_title(text,**kwargs)
"""

Playwright元素常用操作

我们以该网页为例子进行测试
登陆页面,我们输入用户名、密码、验证码,点击登录

同时,我们介绍怎么处理iframe进行上传文件以及自动化,在上传文件中,我们要注意,每一个图片都有一个随机的字符串

在这里插入图片描述
所以我们可以使用父节点定位方式进行定位处理
“//*[@id=‘filePicker’]/div[2]/input”
在这里插入图片描述
接下来是图片的上传,图片我们先使用set_input_files函数,绝对路径处理,前面添加r
r"C:\Users\jinlai\111.jpg"
具体代码如下:

from playwright.sync_api import Playwright, sync_playwright, expect

playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False,slow_mo=2000)
context = browser.new_context()
page = browser.new_page()
page.goto("http://testingedu.com.cn:8000/Home/user/login.html")
#输入用户名
page.fill('//*[@id="username"]','13800138006')
#输入密码
page.fill('//*[@id="password"]','123456')
#输入验证码,这里做了处理
page.fill('//*[@id="verify_code"]','1111')
#点击登录
page.click('//*[@id="loginform"]/div/div[6]/a')

#进入个人信息页面
page.goto("http://testingedu.com.cn:8000/Home/User/info.html")
#点击图片
page.click('//*[@id="preview"]')
#点击点击选择图片按钮
page.frame_locator('//*[@id="layui-layer-iframe1"]').locator("//*[@id='filePicker']/div[2]/input").set_input_files(r"C:\Users\jinlai\111.jpg")
#点击确认使用
page.frame_locator('//*[@id="layui-layer-iframe1"]').locator("//div[@class='saveBtn']").click()
#点击页面的确认保存
page.click("//input[@class='save']")

#关闭浏览器
browser.close()



接下来我们看下拉框怎么处理

#下拉框收货地址处理,我们需要定位到要操作的输入框,然后根据内容属性处理即可

page.select_option('//*[@id="province"]',value='19280')
page.select_option('//*[@id="city"]',value='19281')
page.select_option('//*[@id="district"]',value='19283')
page.select_option('//*[@id="twon"]',value='19285')
from playwright.sync_api import Playwright, sync_playwright, expect

playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False,slow_mo=2000)
context = browser.new_context()
page = browser.new_page()
page.goto("http://testingedu.com.cn:8000/Home/user/login.html")
#输入用户名
page.fill('//*[@id="username"]','13800138006')
#输入密码
page.fill('//*[@id="password"]','123456')
#输入验证码,这里做了处理
page.fill('//*[@id="verify_code"]','1111')
#点击登录
page.click('//*[@id="loginform"]/div/div[6]/a')

#打开地址管理页面
page.goto("http://testingedu.com.cn:8000/Home/User/address_list.html")
#点击增加新地址
page.click("//*[@class='co_blue']")
#点击并输入收货人
page.fill("//*[@name='consignee']","ceshi")
#点击并输入手机或者电话
page.fill("//*[@name='mobile']","13176358824")


#下拉框收货地址处理
page.select_option('//*[@id="province"]',value='19280')
page.select_option('//*[@id="city"]',value='19281')
page.select_option('//*[@id="district"]',value='19283')
page.select_option('//*[@id="twon"]',value='19285')

#点击并输入详细地址
page.fill("//*[@name='address']","凯胜家园小区2号楼2单元802")
#点击报错按钮
page.click("//*[@id='address_submit']")

#刷新页面
page.reload()
#删除新增的地址
page.click('//span[text()="ceshi"]/../..//a[text()="删除"]')
#关闭浏览器
browser.close()

如何获取多个元素

比如说获取所有搜索商品的名字
我们可以使用query_selector_all方法

goods = page.query_selector_all('//div[@class="shop-list-splb p"]//div[@class="shop_name2"]')
for good in goods:
    print(good.text_content().strip())  #strip去除空格

具体代码如下:

from playwright.sync_api import Playwright, sync_playwright, expect

playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False,slow_mo=2000)
context = browser.new_context()
page = browser.new_page()
page.goto("http://testingedu.com.cn:8000/Home/user/login.html")
#输入用户名
page.fill('//*[@id="username"]','13800138006')
#输入密码
page.fill('//*[@id="password"]','123456')
#输入验证码,这里做了处理
page.fill('//*[@id="verify_code"]','1111')
#点击登录
page.click('//*[@id="loginform"]/div/div[6]/a')

#进入地址管理页面
page.goto("http://testingedu.com.cn:8000/Home/User/address_list.html")

#点击搜索框输入内容
page.fill('//input[@class="search_usercenter_text"]','手机')
#点击搜索
page.click('//a[text()="搜索"]')
#query_selector_all方法获取所有元素
goods = page.query_selector_all('//div[@class="shop-list-splb p"]//div[@class="shop_name2"]')
for good in goods:
    print(good.text_content().strip())  #strip去除空格

#关闭浏览器
browser.close()

运行结果之后:
在这里插入图片描述
页面上显示:
在这里插入图片描述
两者相对应。

Playwright元素常用操作

import re

from playwright.sync_api import Playwright, sync_playwright, expect

playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False,slow_mo=5000)
context = browser.new_context()
page = browser.new_page()
page.goto("http://testingedu.com.cn:8000/Home/user/login.html")
#输入用户名
page.fill('//*[@id="username"]','13800138006')
#输入密码
page.fill('//*[@id="password"]','123456')
#输入验证码,这里做了处理
page.fill('//*[@id="verify_code"]','1111')
#点击登录
page.click('//*[@id="loginform"]/div/div[6]/a')

#进入产品站
page.goto("http://testingedu.com.cn:8000/Home/Goods/goodsInfo/id/55.html")

#点击加入购物车
page.click('//*[@id="join_cart"]')
#点击弹层叉号
page.click('//*[@class="layui-layer-ico layui-layer-close layui-layer-close1"]')

#鼠标悬停,我的购物车按钮,以及点击去购物车结算
page.hover('//span[text()="我的购物车"]')
page.click('//a[@class="c-btn"]')

#点击去结算
page.click('//a[text()="去结算"]')

#点击提交订单
page.click('//button[@class="checkout-submit"]')

#获取订单号,我们可以使用正则表达式获取
t = page.locator('//p[@class="succ-p"]').text_content()
print(t)
text = re.findall(r'\d{18}',t)[0]
print(text)

"""
接下来,我们进入到我的订单页面,点击我的订单的时候,我们发现打开了一个新的网页,在selenium中,是通过切换句柄实现的,而在playwright中,我们可以使用新的写法
"""
print("444")
with context.expect_page() as new_page_info:
    page.click('a[target="_blank"]')   #点击我的订单
new_page = new_page_info.value
new_page.wait_for_load_state()
print(new_page.title())

#点击取消订单,并格式化
new_page.click('//em[text()="{}"]/../..//a[text()="取消订单"]'.format(text))

#点击弹层里面的确定按钮
new_page.click('//*[@class="layui-layer-btn layui-layer-btn-"]/a[text()="确定"]')
#刷新页面
new_page.reload()

#关闭浏览器
browser.close()

Playwright自动化框架设计

Playwright作为一个新进的自动化特殊工具,在易用性方面做了很多工作。针对Playwright我们甚至可以不用做任何处理,把它当成一个封装好的第三方库去使用即可。
那么整体的框架又该怎么去设计呢?又该考虑哪些问题呢?
如果我们站在公司的角度上来说,公司层面需要打造一个通用性很强的自动化框架。也就是说a项目能用,b项目也能用。另外还需要将测试结果、测试过程等都完整的输出出来,这是基本条件。不然我们花了很多时间写代码,换一个项目就不能用了,几乎需要从头到尾的再写写一遍,那就没有任何意义。而测试人员都是拿结果的,画的结果越详细越好。除此之外,我们也应该考虑到,在一个公司写一个完整的框架和使用框架,不太可能是一个人去完成。我们需要考虑代码托管和持续集成等等问题。所以大体的思路呢便有了。我们也可以根据刚刚的这个思路细化出一个架构图来
我们可以将整体的架构,从上到下可以分成五个层次。一是数据层、服务层、对象层,用例层和输出层。
数据方面,为了拥有一定的适应性,我们可以设计框架,让它支持多种外部数据格式。如说新老版本的excel、yaml等等。
而服务层方面,因为需要针对excel文件的操作,所以需要自己去封装excel读写库等等。
对象层面,我们实际上是借助于PO思想进行设计就可以了。
用例方面主要是考虑用例该如何去组织,该如何去执行。
当然我们选择pytest,在用例执行的过程中,我们是需要进行日志和报告的输出的。所以我们需要封装日志,并且加入allure测试报告。最后我们需要考虑的是,在整个框架的实现过程中,可能某些第三方库有些人没有安装。为了让框架的执行更加简单一点,我们可以直接将整个框架打包到docker里面,这样去执行。就不用担心环境的问题了。框架设计好之后,我们可以打开pycharm,把目录结构呢大体的来设计一下。
我们新建一个工程。新建好之后呢,按照我们刚刚的设计思路,将整体的目录结构呢可以设置成下面这种样子。
首先我们新建一个python package,比如叫做common,在common中,我们要做的事情呢,一般就是把一些公共用的库在这儿。比如excel的读写啊、日志啊等等,
再新建一个package,比如叫做ddt。我们在利用外部文件来执行测试用例的时候呢,实际上就是一个数据驱动。那我们可以把数据驱动的一些执行的逻辑代码放到此处。
再接着我们需要存放文件。比如说我们的测试用例、日志结果等等,我们可以新建一个文件夹,叫做lib。在lib文件下我们可以再新建一个cases,用来存放用例,再新建一个日志的文件夹,log用于存放日志。
最后我们还可以将结果和报告单独的进行设计。result和report。为了运行方便,我们也可以在根目录下创建一个runner。运行入口,我们可以新建一个runner的文件。那么整体的结构呢我们就可以按照这种格式设计完成了
在这里插入图片描述

Playwright自动化框架之excel文件读取

直接上代码吧
在这里插入图片描述
在这里插入图片描述

import os

import openpyxl


class Reader:
    """
    pip install openpyxl
    读取excel数据文件
    """
    def __init__(self):
        """
        全局变量
        """
        self.workbook = None
        self.sheet = None
        self.rows = 0
        self.r = 0  #表示当前读取到的行数

    def open_excel(self, srcfile):
        """
        打开文件
        :param srcfile:
        :return:
        """
        if not os.path.isfile(srcfile):
            print("%s not exist" % (srcfile))
            return
        #设置读取文件使用编码
        openpyxl.Workbook.encoding = 'utf-8'
        self.workbook = openpyxl.load_workbook(filename=srcfile)
        #默认从第一个sheet文件读取
        self.sheet = self.workbook[self.workbook.sheetnames[0]]
        self.rows = self.sheet.max_row
        self.r = 0
        return

    def get_sheet(self):
        """
        获取sheet名称
        :return:
        """
        sheets = self.workbook.sheetnames
        return sheets

    def set_sheet(self,name):
        """
        切换sheet
        :param name:
        :return:
        """
        self.sheet = self.workbook[name]
        self.rows = self.sheet.max_row
        self.r = 0
        return

    def readline(self):
        """
        逐行读取文件数据
        :return:
        """
        lines = []
        for row in self.sheet.rows:
            line = []
            for cell in row:
                #如果是空行,添加一个空字符串
                if cell.value is None:
                    line.append('')
                else:
                    line.append(cell.value)
            lines.append(line)
        return lines




import os

from common.Excel import NewExcel


def get_reader(srcfile='') -> NewExcel.Reader:
    reader = None

    if not os.path.isfile(srcfile):
        print("%s not exist" % (srcfile))
        return reader

    if srcfile.endswith('.xlsx'):
        reader = NewExcel.Reader()
        reader.open_excel(srcfile)
        return reader


好了,先介绍这里吧~后面再更新哈哈

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

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

相关文章

linux基础简介(一)

1.Linux内核 ​ Linux 系统从应用角度来看,分为内核空间和用户空间两个部分。内核空间是 Linux 操作系统的主要部分,但是仅有内核的操作系统是不能完成用户任务的。丰富并且功能强大的应用程序包是一个操作系统成功的必要件。 ​ Linux 的内核主要由 5…

Android Framework基础面试篇~

在Android应用开发面试中,针对Framework的问题是常被考察的。以下是一些常见的Framework金典面试题目及其详解: 1. 什么是Android应用生命周期?你能描述一下它包含哪几个阶段吗? Android应用生命周期指的是应用从启动到关闭的整…

[oeasy]python0048_注释_comment_设置默认编码格式

注释Comment 回忆上次内容 使用了版本控制 git 制作备份进行回滚 尝试了 嵌套的控制结构 层层 控制 不过 除非 到不得以尽量不要 太多层次的嵌套 这样 从顶到底含义 明确而且 还扁平 扁平 也能 含义明确 还可以 做点什么? 让程序含义 更加明确呢?&…

数据结构学习分享之栈和队列详解

💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:数据结构学习分享⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你了解更多数据结构的知识   🔝🔝 数据结构第五课 1. 前言&a…

文心一言 VS chatgpt (14)-- 算法导论3.2 2~3题

二、证明等式(3.16):a ^ {\log_b c} c ^ {\log_b a}。 文心一言: chatgpt: 我们需要证明的等式为: a log ⁡ b c c log ⁡ b a a^{\log_b c} c^{\log_b a} alogb​cclogb​a。 首先,将 l…

时序预测 | MATLAB实现ARIMA-BP组合模型时间序列预测

时序预测 | MATLAB实现ARIMA-BP组合模型时间序列预测 目录 时序预测 | MATLAB实现ARIMA-BP组合模型时间序列预测预测效果基本介绍模型原理程序设计参考资料 预测效果 基本介绍 时序预测 | MATLAB实现ARIMA-BP组合模型时间序列预测。 模型原理 ARIMA-BP组合模型是一种常用的时间…

2023年第二届材料科学与工程国际会议(CoMSE 2023) | IOP-JPCS出版

会议简介 Brief Introduction 2023年第二届材料科学与工程国际会议(CoMSE 2023) 会议时间:2023年7月21日-23日 召开地点:中国泰州 大会官网:www.icomse.org CoMSE 2023由四川大学、华南理工大学亚热带建筑科学国家重点实验室、国际电气电子和…

PCL学习四:RANSAC-随机采样一致性

参考引用 Point Cloud Library黑马机器人 | PCL-3D点云 1. RANSAC 概念及作用 RANSAC(Random Sample Consensus,随机采样一致性)是一种迭代方法,作用:从包含异常值的一组数据中估计数学模型的参数,RANSAC 算…

AIGC:【LLM(一)】——LoRA微调加速技术

文章目录 一.微调方法1.1 Instruct微调1.2 LoRA微调 二.LoRA原理三.LoRA使用 一.微调方法 Instruct微调和LoRA微调是两种不同的技术。 1.1 Instruct微调 Instruct微调是指在深度神经网络训练过程中调整模型参数的过程,以优化模型的性能。在微调过程中&#xff0c…

Flutter——最详细(TextField)使用教程

TextField简介 文本输入框,拥有复杂的属性。可指定控制器、文字样式、装饰线、行数限制、游标样式等。监听输入框变动事件。 使用场景: 搜索框,输入账号密码等 属性作用controller输入框监听器decoration输入框装饰属性textAlign内容对齐方式…

UE5.1.1 C++ 从0开始 (1.人物移动)

开个天坑,UE5.1.1的移动代码做了一个大更新,对于我这种万年蓝图然后正在转C的人来说可以说是个挑战也可以说是个更方便我去工作的一个点。同时斯坦福大学的那个教程的开头几个章节就不适用了,对于学习UE5.1.1的同学来说。所以我这里会尽量每天…

[230506] 2021年托福阅读真题第6篇|Water and Life on Mars|15:30~16:30|16:30~19:19

正确率:6/10 ​​​​​​​ Water and Life on Mars Paragraph 1: The question of life on Mars depends heavily on the characteristics of its air and water. Mars has a relatively thin and dry atmosphere, with a high percentage of carbon dioxide com…

想转行大数据,需要学习什么?

Python近段时间一直涨势迅猛,在各大编程排行榜中崭露头角,得益于它多功能性和简单易上手的特性,让它可以在很多不同的工作中发挥重大作用。 正因如此,目前几乎所有大中型互联网企业都在使用 Python 完成各种各样的工作&#xff0…

Spark大数据处理讲课笔记3.7 Spark任务调度

文章目录 零、本节学习目标一、有向无环图(一)DAG概念(二)实例讲解 二、Stage划分依据(一)两阶段案例(二)三阶段案例 三、RDD在Spark中的运行流程(一)RDD Obj…

buuctf7

目录 Crypto MD5 Url编码 看我回旋踢 web [极客大挑战 2019]BuyFlag​ [BJDCTF2020]Easy MD5 Crypto MD5 1.下载文件 2.md5在线解密 3.外包flag Url编码 使用url在线解码 看我回旋踢 下载,得到这串字符,搜一下synt编码 看到使用凯撒密码&#x…

2023-05-04:用go语言重写ffmpeg的scaling_video.c示例,用于实现视频缩放(Scaling)功能。

2023-05-04:用go语言重写ffmpeg的scaling_video.c示例,用于实现视频缩放(Scaling)功能。 答案2023-05-04: 这段代码实现了使用 libswscale 库进行视频缩放的功能。下面是程序的主要流程: 1.获取命令行参…

唐书计组第三章总线部分课后习题和解答

我自己的一些总结 总线周期分为哪四个阶段 申请分配阶段寻址阶段存数阶段结束阶段 总线分为哪四种通信方式 同步通信异步通信半同步通信分离式通信 总线有哪几种判优方式 链式查询 计数器定时查询 独立请求方式 计算数据传输率 3.14设总线的时钟频率为8MHz,一个总线周期…

(3)信号槽

目录 1.信号槽的概念 2.信号槽的连接 2.1自带信号 → 自带槽 2.2 自带信号 → 自定义槽 2.3 自定义信号 1.信号槽的概念 信号槽指的是信号函数与槽函数的连接,可以使用不同的对象通过信号槽连接在一起,从而实现对象之间的通信。 可以把信号槽的连接…

数字化经营3.0阶段,云徙科技如何定义“为增长而生”?

作者:Lucky 新时代风云变幻中,通过数字化转型,驱动业务增长、提升运营效率是企业升级的必由之路。如今,数字化经营也已经进入3.0阶段,企业对“人、货、场”三位一体的前端数字化的要求更高,行业也需要更有效…

Java设计模式-建造者模式

简介 建造者模式是一种创建型设计模式,用于将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。建造者模式通过将复杂对象的构建过程分解为多个简单的步骤来实现。 与其他创建型模式不同,建造者模式强调的是将构建过…