Selenium学习(Java + Edge)

news2025/4/8 9:55:02

Selenium

/səˈliːniəm/

1. 简介

​ Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE、Mozilla Firefox、Safari、Google Chrome、Opera、Edge等。

​ 适用于自动化测试,js动态爬虫(破解反爬虫)等领域。

​ Selenium的核心Selenium Core基于JsUnit,完全由JavaScript编写,因此可以用于任何支持JavaScript的浏览器上。selenium可以模拟真实浏览器,自动化测试工具,支持多种浏览器。

Selenium官方

2. 组成

  • Selenium IDE:嵌入到Firefox浏览器中的一个插件,实现简单的浏览器操作录制与回放功能,主要用于快速创建BUG及重现脚本,可转化为多种语言;
  • Selenium RC: 核心组件,支持多种不同语言编写自动化测试脚本,通过其服务器作为代理服务器去访问应用,达到测试的目的;
  • Selenium WebDriver(重点):一个浏览器自动化框架,它接受命令并将它们发送到浏览器。它是通过特定于浏览器的驱动程序实现的。它直接与浏览器通信并对其进行控制。Selenium WebDriver支持各种编程语言,如Java、C# 、PHP、Python、Perl、Ruby;
  • Selenium grid:测试辅助工具,用于做分布式测试,可以并行执行多个测试任务,提升测试效率。

3. 特点

  1. 开源、免费
  2. 多浏览器支持:FireFox、Chrome、IE、Opera、Edge;
  3. 多平台支持:Linux、Windows、MAC;
  4. 多语言支持:Java、Python、Ruby、C#、JavaScript、C++;
  5. 对Web页面有良好的支持;
  6. 简单(API 简单)、灵活(用开发语言驱动);
  7. 支持分布式测试用例执行。

4. 配置

采用Java编写自动化测试代码。

4.1 环境依赖

注意:浏览器版本必须与Selenium驱动版本一致!

Edge:118.0.2088.76 x64

Selenium驱动:118.0.2088.76

Maven依赖:4.8.0

JDK:1.8.0_361

4.2 下载对应浏览器的驱动

注意:下载的驱动包需要与当前浏览器版本对对应。

4.4 配置驱动包

​ 将驱动包解压到jdk / bin目录下。

5. 运行

5.1 创建Maven项目

在这里入图片描述
在这里插入图片描述

5.2 导入Selenium依赖

pom.xml

<dependencies>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.8.0</version>
    </dependency>

    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>
</dependencies>

5.3 在test /java下创建类

在这里插入图片描述

或者直接在src -> main -> java下新建。

5.4 在自动化测试类中编写代码

// 自动化测试类
public class AutoTest  {
    public void Test() throws InterruptedException, IOException {
        // Edge驱动
        EdgeOptions edgeOptions = new EdgeOptions();
        // 允许所有请求(允许浏览器通过远程服务器访问不同源的网页,即跨域访问)
        edgeOptions.addArguments("--remote-allow-origins=*");
        EdgeDriver edgeDriver = new EdgeDriver(edgeOptions);
        // 启动需要打开的网页
        edgeDriver.get("https://www.baidu.com");
        // 退出
        edgeDriver.quit();
    }
}
import java.io.IOException;

// 启动类
public class RunAutoTest {
    public static void main(String[] args) throws InterruptedException, IOException {
        AutoTest autoTest = new AutoTest();
        autoTest.Test();
    }
}

5.5 启动

6. 使用

6.1 请求

方法说明
driver.get(url)请求一个页面,不支持前进和后退切换
driver.navigate().to(url)和get类似,支持前进和后退切换
driver.navigate().forward(url)指前进到下一个页面(必须后退一个页面后才能前进)
driver.navigate().back(url)退到上一个页面(必须前进了一个页面才能回退)
driver.navigate().refresh(url)刷新当前页面

6.2 定位元素

方法描述
driver.findElement(By.id())使用元素的唯一标识ID进行定位
driver.findElement(By.name())使用元素的名称属性进行定位
driver.findElement(By.className())使用元素的类名进行定位
driver.findElement(By.tagName)使用元素的标签名进行定位
driver.findElement(By.partialLinkText())使用链接文本进行定位
driver.findElement(By.cssSelector)使用CSS选择器进行定位
driver.findElement(By.xpath)使用XPath表达式进行定位

cssSelector:

在这里插入图片描述

cv工程


元素定位—cssSelector

  1. 根据tagName

    By.cssSelector("input");// 不推荐,tagName会重复
    
  2. 根据ID

    By.cssSelector("input#id");
    By.cssSelector("#id");
    
  3. 根据className(样式名)

    By.cssSelector(".className");
    By.cssSelector("input.className");
    

css精确定位

  1. 根据元素属性,属性名=属性值(id、calss等都可使用此形式)

    // By.cssSelector("标签名[属性名='属性值']");
    By.cssSelector("input[name='xxx']");
    
  2. 多属性

    By.cssSelector("标签名[属性名='属性值'][属性名='属性值']");
    

6.3 获取内容

方法说明
String getPageSource()获取页面html
String getTitle()获取页面标题
String getText()获取此元素(包括子元素)的可见(即未被CSS隐藏)文本
String getTagName()获取此元素的标签名
String getAttribute(String name)获取元素指定属性的值
Point getLocation()获取当前元素,基于页面左上角的为准
Dimension getSize()渲染元素的宽度和高度是多少
String getCurrentUrl()获取表示浏览器正在查看的当前URL的字符串
String getCssValue(String propertyName)获取指定元素的CSS属性的值

6.4 操作行为

方法说明
clear()如果该元素是文本输入元素,则会清除该值
submit()提交from表单
click()单击此元素
sendKeys()使用此方法模拟在元素中键入,可以设置其值

注意:

有些页面是使用动态加载js的,会导致html页面正常显示,但js还没执行完毕,相关事件还没绑定到具体的元素上。导致出现操作无效或程序抛出异常。

可以在加载页面时强制等待,全部加载完毕后再进行后续操作。

6.5 窗口

方法说明
driver.manage().window().setSize(new Dimension(1024, 768))设置当前窗口的大小
driver.manage().window().setPosition()设置当前窗口的位置(相对于屏幕的左上角)
driver.manage().window().getSize()获取当前窗口的大小
driver.manage().window().getPosition()获取当前窗口相对于屏幕左上角的位置
driver.manage().window().fullScreen()全屏当前窗口
driver.manage().window().maximize()最大化当前窗口

6.6 切换指定窗口

​ 当浏览器每次打开一个标签页的时候,会自动的给一个标签进行标识,这个标识我们称之为“句柄”。

方法说明
String getWindowHandle()返回当前窗口句柄,通过将其传递给switchTo(),进行切换窗口
driver.switchTo().window(windowHandle)切换到指定句柄的窗口
    String curHandle = edgeDriver.getWindowHandle();// 获取当前页面句柄
    System.out.println("当前句柄:" + curHandle);
    Set<String> handles = edgeDriver.getWindowHandles();// 获取所有页面句柄
    for (String handle : handles) {
        if (!handle.equals(curHandle)) {// 发生页面切换
            edgeDriver.switchTo().window(handle);// 切换窗口
        }
    }

6.7 iframe切换

方法说明
driver.switchTo().frame(index)根据index进行切换
driver.switchTo().frame(id)根据id进行切换
driver.switchTo().frame(name)根据name进行切换
driver.switchTo().frame(WebElement)根据WebElement进行切换
driver.switchTo().defaultContent()切换后,回到默认内容页面(否则会找不到元素)

6.8 模拟键盘和鼠标

6.8.1 键盘事件
方法说明
driver.findElement(By.id(“kw”)).sendKeys(Keys.CONTROL, “a”)ctrl+a
driver.findElement(By.id(“kw”)).sendKeys(Keys.CONTROL, “c”)ctrl+c
driver.findElement(By.id(“kw”)).sendKeys(Keys.CONTROL, “v”)ctrl+v
driver.findElement(By.id(“kw”)).sendKeys(Keys.TAB)TAB键
driver.findElement(By.id(“kw”)).sendKeys(Keys.ENTER)回车键
driver.findElement(By.id(“kw”)).sendKeys(Keys.SPACE)空格键
6.8.2 鼠标事件
Actions actions = new Actions(driver);
方法说明
actions.contextClick(element).perform()右键点击enement的元素
actions.clickAndHold(element).perform()左键单击enement元素
actions.doubleClick(element).perform()鼠标左键双击enement元素
actions.moveToElement(element).perform()鼠标悬停enement元素(中间)
actions.moveToElement(element,x,y).perform()鼠标悬停enement元素(指定位置)
actions.moveToElement(x,y).perform();将鼠标从其当前位置移动鼠标
Actions dragAndDrop(WebElement source, WebElement target)拖动元素, 在源元素的位置执行点击并保持,移动到目标元素的位置,然后释放鼠标
Actions dragAndDropBy(WebElement source, int xOffset, int yOffset) 拖动到指定位置拖动到指定位置

6.9 等待

6.9.1 强制等待
    Thread.sleep(millisecond);

程序阻塞执行,不建议。

6.9.2 显式等待

​ 显式等待是添加到代码中的循环,在应用程序退出循环并继续执行代码中的下一个命令之前,它会轮询应用程序以查找特定条件以评估为true。如果在指定的超时值之前未满足条件,则代码将给出超时错误。

WebElement revealed = driver.findElement(By.id("revealed"));
Wait<WebDriver> wait = new WebDriverWait(driver, Duration.ofSeconds(2));

driver.findElement(By.id("reveal")).click();
wait.until(d -> revealed.isDisplayed());

revealed.sendKeys("Displayed");
6.9.3 隐式等待

​ 这是一个全局设置,适用于整个会话的每个元素位置调用。默认值为0,这意味着如果找不到元素,它将立即返回错误。如果设置了隐式等待,则在返回错误之前,驱动程序将等待所提供值的持续时间。请注意,一旦找到元素,驱动程序将返回元素引用,代码将继续执行,因此较大的隐式等待值不一定会增加会话的持续时间。

driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));

注意:

​ 不要混合隐式和显式等待。这样做可能会导致不可预测的等待时间。

​ 例如,设置10秒的隐式等待和15秒的显式等待可能会导致20秒后发生超时。

6.10 弹窗

  1. 警告弹窗中, 切换到弹窗,调用 accept()
  2. 确认弹窗中, 切换到弹窗,调用 accept() 或者 dismiss()
  3. 提示弹窗中, 切换到弹窗, 可以先输入文本, 调用 sendKeys(), 然后调用 accept() 或者 dismiss().
    提示:这里的 sendKeys() 在页面上看不到输入文本的执行效果
driver.get("...");
Thread.sleep(3000);

// 打开弹窗
driver.findElement(By.cssSelector("body > input[type=button]")).click();
Thread.sleep(3000);

// 切换到弹窗进行弹窗的处理
Alert alert = driver.switchTo().alert();
Thread.sleep(3000);

// 弹窗输入文本
alert.sendKeys("abcdef");

// 点击确认
alert.accept();

// 点击取消
// alert.dismiss();

driver.quit();
6.10.1 警告弹窗

警告弹窗中, 切换到弹窗,调用 accept()

6.10.2 确认弹窗

确认弹窗中, 切换到弹窗,调用 accept() 或者 dismiss()

6.10.3 提示弹窗

提示弹窗中, 切换到弹窗, 可以先输入文本, 调用 sendKeys(), 然后调用 accept() 或者 dismiss().
提示:这里的 sendKeys() 在页面上看不到输入文本的执行效果

6.11 下拉选择框

方法说明
select.getOptions()获取所有选项
select.selectByIndex(index)根据索引选中对应的元素
select.selectByValue(value)选择指定value值对应的选项
select.selectByVisibleText(text)选中文本值对应的选项
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<select name="ss" id="sss">
    <option value="12.5">**12.5**</option>
    <option value="6.6">**6.6**</option>
    <option value="486.4">**486.4**</option>
    <option value="21.12">**21.12**</option>
    <option value="99.99">**99.99**</option>
</select>
</body>
</html>
package org.example;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.support.ui.Select;

import java.time.Duration;

public class Main {
    public static void main(String[] args) throws Exception {
        EdgeOptions edgeOptions = new EdgeOptions();
        edgeOptions.addArguments("--remote-allow-origins=*");
        EdgeDriver edgeDriver = new EdgeDriver(edgeOptions);
        edgeDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));// 隐式等待

        edgeDriver.get("file:///D:/idea-workspace/WebTest/src/main/resources/web/fileUpload/select.html");

//        WebElement webElement = edgeDriver.findElement(By.cssSelector("sss"));
//        Select select = new Select(webElement);
        Select select = new Select(edgeDriver.findElement(By.cssSelector("#sss")));

        // 根据文本选择
        Thread.sleep(3000);
        select.selectByVisibleText("**99.99**");

        // 根据索引值选择
        Thread.sleep(3000);
        select.selectByIndex(1);

        // 根据属性值选择
        Thread.sleep(3000);
        select.selectByValue("6.6");

        Thread.sleep(1000);
        edgeDriver.quit();
    }
}
6.11.1 根据文本选择
WebElement webElement = driver.findElement(By.cssSelector("#Method"));

// 创建选择框对象(将此web元素封装为Select对象)
Select select = new Select(webElement)

// 根据文本来选择
select.selectByVisibleText("选择框文本");

Thread.sleep(3000);
driver.quit();
6.11.2 根据属性值选择
WebElement webElement = driver.findElement(By.cssSelector("#Method"));

// 创建选择框对象(将此web元素封装为Select对象)
Select select = new Select(webElement)

// 根据属性值来选择
select.selectByValue("选择框属性值");

Thread.sleep(3000);
driver.quit();
6.11.3 根据序号选择

注意:select下拉框索引值从0开始!

WebElement webElement = driver.findElement(By.cssSelector("#Method"));

// 创建选择框对象(将此web元素封装为Select对象)
Select select = new Select(webElement)

// 根据序号来选择
select.selectByIndex(1);

Thread.sleep(3000);
driver.quit();

6.12 文件上传

public void fileUploadController() throws InterruptedException {
	driver.get("");
	Thread.sleep(3000);
	
	driver.findElement(By.cssSelector("body > div > div > input[type=file]")).sendKeys("文件路径");
	Thread.sleep(3000);
	driver.quit();
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<input type="file" id="fu" value="选择文件">
<br>
<input type="button" id="fw" value="上传">
</body>
</html>

package org.example;

import org.openqa.selenium.By;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;

import java.time.Duration;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("Hello world!");
        EdgeOptions edgeOptions = new EdgeOptions();
        edgeOptions.addArguments("--remote-allow-origins=*");
        EdgeDriver edgeDriver = new EdgeDriver(edgeOptions);
        edgeDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));// 隐式等待

        edgeDriver.get("file:///D:/idea-workspace/WebTest/src/main/resources/web/fileUpload/fileUpload.html");
        Thread.sleep(3000);

        edgeDriver.findElement(By.cssSelector("#fu")).sendKeys("D:/idea-workspace/WebTest/src/main/resources/web/fileUpload/fileUpload.html");

        Thread.sleep(3000);
        edgeDriver.quit();

    }
}

在这里插入图片描述
在这里插入图片描述

注意:如果上传文件前端控件源码不是input类型,需要使用第三方工具,比如:autoit

6.13 时间日期控件

  • 控件没有限制手动输入,则直接调用sendKeys方法写入时间数据。
  • 控件有限制输入,则可以通过执行一段js脚本来改变元素的value属性值。
6.13.1 方式一
package org.example;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.support.ui.Select;

import java.time.Duration;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        EdgeOptions edgeOptions = new EdgeOptions();
        edgeOptions.addArguments("--remote-allow-origins=*");
        EdgeDriver edgeDriver = new EdgeDriver(edgeOptions);
        edgeDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));// 隐式等待

        edgeDriver.get("https://www.fliggy.com/?ttid=seo.000000580&seoType=origin");
        edgeDriver.findElement(By.cssSelector("#J_FlightForm > fieldset > div:nth-child(5) > div > div > input")).sendKeys("2000-01-01");

        Thread.sleep(1000);
        edgeDriver.quit();
    }
}
6.13.2 方式二
	见 6.13 执行脚本

6.13 执行脚本

方法说明
driver.executeScript()参数为要执行的js脚本
package org.example;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.support.ui.Select;

import java.time.Duration;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        EdgeOptions edgeOptions = new EdgeOptions();
        edgeOptions.addArguments("--remote-allow-origins=*");
        EdgeDriver edgeDriver = new EdgeDriver(edgeOptions);
        edgeDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));// 隐式等待

        edgeDriver.get("https://www.12306.cn/index/");
//        edgeDriver.findElement(By.id("train_date"));
//        edgeDriver.executeScript("var v = train_date;\n" + "v.autocomplete = true");
        edgeDriver.executeScript("var v = train_date; v.autocomplete = true");
        edgeDriver.findElement(By.id("train_date")).clear();
        edgeDriver.findElement(By.id("train_date")).sendKeys("2000-01-01");

        Thread.sleep(1000);
        edgeDriver.quit();
    }
}

在这里插入图片描述

在这里插入图片描述

6.14 浏览器参数设置

EdgeOptions edgeOptions = new EdgeOptions();
edgeOptions.addArguments("--remote-allow-origins=*");
addArguments可接收参数说明
“–disable-gpu”禁用GPU加速
“–headless”在无头模式下运行浏览器,即不显示图形界面
“–incognito”在隐身模式下启动浏览器
“–disable-extensions”禁用浏览器扩展
“–disable-notifications”禁用浏览器通知
“–disable-popup-blocking”禁用弹出窗口拦截功能
“–start-maximized”启动时最大化浏览器
“–disable-infobars”禁用信息栏(例如Chrome正在受到自动测试软件控制)
“–ignore-certificate-errors”忽略证书错误
“–proxy-server=http://hostname:port”设置代理服务器

注意:浏览器的参数设置需要在创建浏览器对象之前进行设置。

6.15 验证码

6.15.1 万能验证码(推荐)

​ 后端代码添加测试通用验证码。

6.15.2 去除验证码

​ 后端去除验证码。

6.15.3 自动识别(难度大)

​ 可以付费调用自动识别API,不推荐。

6.16 退出

方法说明
driver.close()关闭当前窗口(如果是当前打开的最后一个窗口,则退出浏览器)
driver.quit()退出此驱动程序,关闭每个相关窗口

在操作完毕后必须调用quit()进行释放资源,否则驱动将持续在内存中不会被释放掉。

7. 最后

码字不易,xdm,qiuqiu点个👍吧!
在这里插入图片描述

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

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

相关文章

Linux期末复习——文件I/O编程

Linux系统调用以及用户编程接口 三者关系 系统调用、API以及系统命令之间关系&#xff1a; 什么是文件描述符&#xff1f; 是一个非负整数&#xff0c;索引值 打开或者创建一个文件的时候&#xff0c;内核会向进程返回一个文件描述符 读写文件时&#xff0c;会向函数传递一个文…

ModuleNotFoundError: No module named ‘paddle.fluid.incubate.fleet‘

在使用rocketqa的时候可能会遇到下面的问题&#xff1a; 问题&#xff1a; 解决方法&#xff1a; 这完全是paddlepaddle的问题。 在rocketqa/utils/optimization.py出现下面的语句&#xff0c;这个时候直接把出错的注释掉就可以&#xff0c;因为它完全没有用到。&#xff08;…

Win10奇怪的部分文字乱码问题

1.打开Windows设置的时间和语言 2.打开区域下方的的其他日期、时间和区域设置 3.点击更改日期、时间或数字格式。切换到管理 4.点击更改系统区域设置&#xff0c;取消Beta版&#xff1a;使用Unicode UTF-8提供全球语言支持。 按提示重启电脑即可。

Windows电脑怎么下载桌面便签小工具?

Windows电脑是日常办公中常用的工具&#xff0c;电脑上可以安装许多软件来辅助日常办公&#xff0c;其中桌面便签工具可以为大家记录很多日常办公中的各项工作计划&#xff0c;而且便签软件通常可以悬挂于电脑桌面显示&#xff0c;方便大家一边工作一边查看备忘记录。 谈及Win…

探索网络攻击:ARP断网、ARP欺骗和DNS欺骗实验解析

目录 前言 一、ARP概述 1.1 什么是ARP 1.2 ARP协议的基本功能 1.3 ARP缓存表 1.4 ARP常用命令 二、ARP断网实验 三、ARP欺骗实验 3.1 内网截获图片 3.2 HTTP账户密码获取 四、DNS欺骗实验 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&…

OpenGL ES入门教程(一)编写第一个OpenGL程序

OpenGL ES入门教程&#xff08;一&#xff09;编写第一个OpenGL程序 前言 从本文开始我将参考学习OpenGL ES应用开发实践指南 Android卷 [&#xff08;美&#xff09;KevinBrothaler著]&#xff08;提取码: 394m&#xff09;&#xff0c;并基于自己的理解以更加通俗易懂的方式…

[.NET]桃源网络硬盘 v7.4

桃源网络硬盘是一个以.net进行开发的网络硬盘系统源码。 开发环境&#xff1a;Microsoft.NET Framework SDK 运行要求&#xff1a; Windows 2003及以上版本 或 Windows XP及以上版本&#xff0c;安装 .Net Framework 要求上传目录有写权限 请将其放在虚拟目录或单独的网页空间…

Kubernetes包管理工具Helm简介及使用

文章目录 前言技术积累什么是HelmHelm的核心概念Helm可以解决哪些痛点Helm中文官方文档 Helm安装Helm安装nginx用例写在最后 前言 大家都知道K8S是云原生devops的一大利器&#xff0c;可以直接让我们的中间件、应用服务直接运行在云端&#xff0c;让我们可以只关心自身的业务功…

【Unity】【VR开发疑难】Unity运行就报无法启动XR Plugin

【现象】 连接Link后运行Unity的VR项目Link也无反映&#xff0c;Unity控制台报&#xff1a;无法启动XR Plugin&#xff0c;并说是由于Oculus头盔未连接导致。 【分析】 打开Oculus PC客户端&#xff0c;发现状态是连接正常。重启机器后&#xff0c;提示Oculus没有出于RunTim…

概念解析 | 揭开心电图测量的神秘面纱

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:ECG的测量原理 揭开心电图测量的神秘面纱 How to read an ECG – Physical Therapy Reviewer 1. 背景介绍 心电图(ECG)是记录心脏电活动的过程,它反映了心脏在收缩和舒张期间的…

新一代构建工具Vite-xyphf

一、什么vite? vite:是一款思维比较前卫而且先进的构建工具,他解决了一些webpack解决不了的问题——在开发环境下可以实现按需编译&#xff0c;加快了开发速度。而在生产环境下&#xff0c;它使用Rollup进行打包&#xff0c;提供更好的tree-shaking、代码压缩和性能优化&…

创建javaEE项目(无maven),JSP(九大内置对象)、Servlet(生命周期)了解

一、Servlet和jsp 0.创建web项目(无maven)&#xff1a; 1.创建一个普通的java项目 2.项目根目录右键&#xff0c;添加模板 3.配置tomcat服务器 4.配置项目tomcat依赖 1.Servlet(Server Applet)服务端小程序 用户通过浏览器发送一个请求&#xff0c;服务器tomcat接收到后&…

串口通信(7)判断数据帧头来接收一串数据

本文为博主 日月同辉&#xff0c;与我共生&#xff0c;csdn原创首发。希望看完后能对你有所帮助&#xff0c;不足之处请指正&#xff01;一起交流学习&#xff0c;共同进步&#xff01; > 发布人&#xff1a;日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…

微信小程序:两层循环的练习,两层循环显示循环图片大图(大图显示、多层循环)

效果 代码分析 外层循环 外层循环的框架 <view wx:for"{{info}}" wx:key"index"></view> wx:for"{{info}}"&#xff1a;这里wx:for指令用于指定要遍历的数据源&#xff0c;即info数组。当遍历开始时&#xff0c;会依次将数组中的每…

链表的结点个数统计及查找

链表节点个数统计 要统计链表中的节点个数&#xff0c;只需要遍历整个链表&#xff0c;并在遍历的过程中计数即可。具体实现代码如下&#xff1a;(仍然使用C#) 先定义一个整型函数(节点个数的返回值一定是整型变量) int getLinkNodeNum(struct Test *head) {int cnt 0;whil…

STM32:AHT20温湿度传感器驱动程序开发

注&#xff1a;温湿度传感器AHT20数据手册.pdf http://www.aosong.com/userfiles/files/AHT20%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6(%E4%B8%AD%E6%96%87%E7%89%88)%20B1.pdf 一、分析AHT数据手册文档 (1).准备工作 1.新建工程。配置UART2 2.配置I2C1为I2C标准模式&…

数据链路层中存在的报文ip,arp,rarp

IP数据报 ARP请求/应答报 RARP请求/应答报 IP数据报 这里的目的地址和源地址是MAC地址。 这个被称为 MAC 地址&#xff0c;是一个网卡的物理地址&#xff0c;用十六进制&#xff0c;6 个 byte 表示。 MAC 地址是一个很容易让人误解的地址。因为 MAC 地址号称全球唯一&…

深度学习_7_实战_点集最优直线解_优化版代码解析

完整版优化代码&#xff1a; import torch from torch.utils import data from d2l import torch as d2l # 特定导入 from torch import nndef load_array(data_arrays, batch_size, is_trainTrue):dataset data.TensorDataset(*data_arrays) #解包传递&#xff0c;转成张量…

【Linux】Nignx的入门使用负载均衡前端项目部署---超详细

一&#xff0c;Nignx入门 1.1 Nignx是什么 Nginx是一个高性能的开源Web服务器和反向代理服务器。它使用事件驱动的异步框架&#xff0c;可同时处理大量请求&#xff0c;支持负载均衡、反向代理、HTTP缓存等常见Web服务场景。Nginx可以作为一个前端的Web服务器&#xff0c;也可…

使用docker进行nextcloud+onlyoffice环境搭建(在线 or 离线)

1.安装 MySQL&#xff08;有MySQL就可以不装&#xff09; docker run -itd --name mysql8.0 -p 3306:3306 -e MYSQL_ROOT_PASSWORDroot --restartalways -e TZ"Asia/Shanghai" -v /home/docker/workspace/mysql:/var/lib/mysql mysql:latest --lower_case_table_na…