自动化测试-Selenium

一. Selenium介绍

selenium 是用来做web自动化测试的框架,支持各种浏览器,各种,支持各种语言 

原理:

二. 元素定位

2.1 XPath 定位

绝对路径: /html/head/title

相对路径以双斜杠开头,常见的相对路径定位有以下几种:

<1>相对路径+索引: 索引是从1开始的

<2>相对路径+属性值:

<3>相对路径+通配符

<4>相对路径+文本匹配

2.2 CSS定位

• id选择器: #id

• 类选择器: .class

• 标签选择: 标签名

• 后代选择器: 父级选择器 子级选择器

三. 操作测试对象

3.1 常见API

• click 点击对象

• send_keys 在对象上模拟按键输入

• clear 清除对象输入的文本内容

• submit 提交

• getAttribute 获取标签中value属性所对应的值

• text 由于获取元素的文本信息

public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        //允许所有请求
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver =new ChromeDriver(options);
        //获取网址
        webDriver.get("https://www.sogou.com");
        //获取value标签元素文本信息
        String str=webDriver.findElement(By.xpath("//input[@value=\"搜狗搜索\"]")).getAttribute("value");
        System.out.println(str);
        //输入搜索内容
        webDriver.findElement(By.cssSelector("#query")).sendKeys("软件测试");
        Thread.sleep(3000);
        webDriver.findElement(By.xpath("//input[@value=\"搜狗搜索\"]")).click();
        Thread.sleep(3000);
        //找到并打印所有a标签下em标签中的内容
        List<WebElement> elements=webDriver.findElements(By.cssSelector("a em"));
        for (int i = 0; i < elements.size(); i++) {
            System.out.println(elements.get(i).getText());
        }
        Thread.sleep(3000);
        webDriver.close();

    }
}
public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("https://www.sogou.com/");
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#query")).sendKeys("软件测试");
        Thread.sleep(3000);
        //由于此处的搜狗搜索在form标签中,因此能够顺利提交
        //webDriver.findElement(By.cssSelector("#stb")).click();
        webDriver.findElement(By.cssSelector("#stb")).submit();
        Thread.sleep(3000);
        //此时代码是会报错的,因为a标签并不在form标签内
        //webDriver.findElement(By.cssSelector("#weixinch")).submit();
        webDriver.close();
    }

3.2 等待

public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("https://www.baidu.com/");
        webDriver.findElement(By.cssSelector("#s-top-loginbtn")).click();
        //隐式等待
        //webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.DAYS);
        //显示等待,若加载出直接执行下面代码,若在指定时间内没有加载出来,就抛异常
        new WebDriverWait(webDriver,10).until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#s-top-loginbtn")));
        //强制等待3s
        Thread.sleep(3000);
        webDriver.findElement(By.xpath("//*[@id=\"TANGRAM__PSP_11__userName\"]")).sendKeys("1111");
        webDriver.close();
    }

隐式等待等待的是整个页面的元素,而显示等待等待的是一定的条件. 

3.3 打印信息(标题/URL)

    public static void main(String[] args) {
        ChromeOptions options =new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("https://www.sogou.com/");
        String title=webDriver.getTitle();
        String url=webDriver.getCurrentUrl();
        System.out.println("当前标题:"+title+"当前url:"+url);
        webDriver.close();
    }

3.4 浏览器的操作

    public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("https://www.sogou.com");
        webDriver.findElement(By.cssSelector("#query")).sendKeys("软件测试");
        webDriver.findElement(By.cssSelector("#stb")).click();
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.DAYS);
        //后退一步
        webDriver.navigate().back();
        Thread.sleep(3000);
        //前进一步
        webDriver.navigate().forward();
        Thread.sleep(3000);
        //使屏幕最大化
        webDriver.manage().window().maximize();
        Thread.sleep(3000);
        //全屏
        webDriver.manage().window().fullscreen();
        Thread.sleep(3000);
        //自定义窗口大小
        webDriver.manage().window().setSize(new Dimension(600,1000));
        Thread.sleep(3000);
        //滑动滚动条
        ((JavascriptExecutor)webDriver).executeScript("document.documentElement.scrollTop=19999");
    }

3.5 键盘事件

通过sendKeys()调用按键:

• sendkeys(Keys.TAB) #TAB

• sendKeys(Keys.ENTER) #回车

• sendKeys(Keys.SPACE) #空格键

• sendKeys(Keys.ESCAPE) #回退键(Esc)

  public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("https://www.sogou.com/");
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#query")).sendKeys("软件测试");
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#query")).sendKeys(Keys.SPACE);
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#query")).sendKeys("软件开发");
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#query")).sendKeys(Keys.ENTER);
    }

键盘组合键用法 

sendKeys(Keys.CONTROL,"a") #全选 (Ctrl+a)

sendKeys(Keys.CONTROL,"c") #复制 (Ctrl+c)

sendKeys(Keys.CONTROL,"x") #剪切 (Ctrl+x)

sendKeys(Keys.CONTROL,"v") #粘贴 (Ctrl+v)

    public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("https://www.sogou.com/");
        webDriver.findElement(By.cssSelector("#query")).sendKeys("软件测试");
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#query")).sendKeys(Keys.CONTROL,"a");
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#query")).sendKeys(Keys.CONTROL,"x");
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#query")).sendKeys(Keys.CONTROL,"v");
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#query")).sendKeys(Keys.ENTER);
    }

3.6 鼠标事件

Actions类:

• contextClick() 右击

• doubleClick() 双击

• dragAndDrop() 拖动

• moveToElement() 移动

    public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("https://www.sogou.com/");
        webDriver.findElement(By.cssSelector("#query")).sendKeys("软件测试");
        webDriver.findElement(By.cssSelector("#query")).sendKeys(Keys.ENTER);
        Actions actions=new Actions(webDriver);
        Thread.sleep(3000);
        //需要现将鼠标移动到要操作的元素,然后右击,要perform()才会有效果
        actions.moveToElement( webDriver.findElement(By.cssSelector("#sogou_weixin"))).contextClick().perform();
    }

四. 特殊操作

为了方便测试的演示,测试的页面都是自制的。

4.1 定位一组元素

页面:

<!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>
    <h3>checkbox</h3>
<div class="well">
<form class="form-horizontal">
<div class="control-group">
<label class="control-label" for="c1">checkbox1</label>
<div class="controls">
<input type="checkbox" id="c1" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="c2">checkbox2</label>
<div class="controls">
<input type="checkbox" id="c2" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="c3">checkbox3</label>
<div class="controls">
<input type="checkbox" id="c3" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="r">radio1</label>
<div class="controls">
<input type="radio" id="r1" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="r">radio2</label>
<div class="controls">
<input type="radio" id="r2" />
</div>
</div>
</form>
</div>
</body>
</html>

测试: 

    public static void main(String[] args) {
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("http://localhost:63342/SeleniumTest/page/test1.html?_ijt=a28mk13t2kbijoe7d2clon53lj&_ij_reload=RELOAD_ON_SAVE");
        webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.DAYS);
        List<WebElement> webElements=webDriver.findElements(By.xpath("//input[@type=\"checkbox\"]"));
        for (int i = 0; i < webElements.size(); i++) {
            System.out.println(webElements.get(i).getAttribute("type"));
        }
    }

4.2 多层框架/窗口定位

多框架定位

如果有内嵌网页框架,需要先转到框架才能操作框架内元素。

    public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        //允许所有请求
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver =new ChromeDriver(options);
        webDriver.get("https://mail.163.com/");
        //需要先定位到框架,再对框架内元素进行操作
        webDriver.switchTo().frame(webDriver.findElement(By.xpath("//iframe")));
        Thread.sleep(3000);
        webDriver.findElement(By.xpath("//input[@name=\"email\"]")).sendKeys("12345");
    }

窗口的切换

在浏览器中每个窗口都有一个句柄来标识

    public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("Https://www.baidu.com");
        //获取当前句柄
        String handle= webDriver.getWindowHandle();
        System.out.println(handle);
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
        Set<String> hanles=webDriver.getWindowHandles();
        for (String h:hanles) {
            handle=h;
        }
        webDriver.switchTo().window(handle);
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#ww")).sendKeys("新闻联播");
        Thread.sleep(3000);
        webDriver.findElement(By.cssSelector("#s_btn_wr")).click();
    }

4.3 下拉框操作

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>下拉框</title>
</head>
<body>
<select id="ShippingMethod"
        onchange="updateShipping(options[selectedIndex]);" name="ShippingMethod">
  <option value="12.51">UPS Next Day Air ==> $12.51</option>
  <option value="11.61">UPS Next Day Air Saver ==> $11.61</option>
  <option value="10.69">UPS 3 Day Select ==> $10.69</option>
  <option value="9.03">UPS 2nd Day Air ==> $9.03</option>
  <option value="8.34">UPS Ground ==> $8.34</option>
  <option value="9.25">USPS Priority Mail Insured ==> $9.25</option>
  <option value="7.45">USPS Priority Mail ==> $7.45</option>
  <option value="3.20" selected="">USPS First Class ==> $3.20</option>
</select>
</body>
</html>
    public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("http://localhost:63342/SeleniumTest/page/test3.html?_ijt=dcl94qtill9arl6odicib469be&_ij_reload=RELOAD_ON_SAVE");
        WebElement webElement=webDriver.findElement(By.cssSelector("#ShippingMethod"));
        Select select=new Select(webElement);
        Thread.sleep(3000);
        //通过标签 value选择 
        select.selectByValue("9.03");
        Thread.sleep(3000);
        //通过下标选择,下标从零开始
        select.selectByIndex(2);
    }

4.4 弹窗操作

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button onclick="Click()">这是一个弹窗</button>
</body>
<script type="text/javascript">
  function Click() {
    let name = prompt("请输入姓名:");
    let parent = document.querySelector("body");
    let child = document.createElement("div");
    child.innerHTML = name;
    parent.appendChild(child)
  }
</script>
</html>
    public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("http://localhost:63342/SeleniumTest/page/test4.html?_ijt=e7mju27ab5d214o41bhvcqjf4r&_ij_reload=RELOAD_ON_SAVE");
        webDriver.findElement(By.xpath("//*[text()=\"这是一个弹窗\"]")).click();
        Thread.sleep(3000);
        //alert弹窗取消
        webDriver.switchTo().alert().dismiss();
        Thread.sleep(3000);
        webDriver.findElement(By.xpath("//*[text()=\"这是一个弹窗\"]")).click();
        Thread.sleep(3000);
        webDriver.switchTo().alert().sendKeys("软件测试");
        Thread.sleep(3000);
        webDriver.switchTo().alert().accept();
    }

4.5 文件操作

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<input type="file">
</body>
</html>
    public static void main(String[] args) {
        ChromeOptions options =new ChromeOptions();
        options.addArguments("--remote-allow-origins");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("http://localhost:63342/SeleniumTest/page/test5.html?_ijt=klnnrj3i4pn2rhg6cl7a63qibe&_ij_reload=RELOAD_ON_SAVE");
        webDriver.findElement(By.cssSelector("input")).sendKeys("E:\\test");
    }

4.6 quit和close

quit 关闭了整个浏览器,同时会清空浏览器的cookie,close关闭的是get时获取的页面.

    public static void main(String[] args) throws InterruptedException {
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver=new ChromeDriver(options);
        webDriver.get("https://www.baidu.com");
        webDriver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
        Thread.sleep(3000);
        //webDriver.close();
        webDriver.quit();
    }

 4.7 截图

    public static void main(String[] args) throws InterruptedException, IOException {
        WebDriver webDriver=new ChromeDriver();
        webDriver.get("Https://www.baidu.com");
        webDriver.findElement(By.cssSelector("#kw")).sendKeys("软件测试");
        webDriver.findElement(By.cssSelector("#su")).click();
        Thread.sleep(3000);
        File file=((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(file,new File("E:\\Code\\SeleniumTest\\picture.png"));
    }

注:截图操作需要另外引入一个common-io的依赖

Maven Repository: commons-io » commons-io » 2.11.0 (mvnrepository.com)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GIS入门,开源 JavaScript二维地图引擎OpenLayers介绍

VueOpenLayers中文教程推荐&#xff0c;不同于OpenLayers官方文档使用htmljs原生原生教程&#xff0c;博主专栏包含大量vue整合案例和实际开发案例&#xff0c;非常适合地图开发小白快速入门。 vue整合OpenLayers6入门教程&#xff1a; 《VueOpenLayers入门教程汇总目录》vue整…

企业编码生成程序Python毕业设计

&#xff08;1&#xff09;生成6位数字防伪编码。当用户在主程序界面中输入数字“1”菜单项时&#xff0c;将进入“生成6位数字防伪编码 &#xff08;213563型&#xff09;”的功能执行任务。此时要求输入生成防伪码的数量&#xff0c;可以根据需要输入生成防伪码的数量。按下&…

Proteus仿真--基于数码管显示的频率计设计

本文介绍基于数码管的频率计设计&#xff08;完整仿真源文件及代码见文末链接&#xff09; 仿真图如下 本设计中80C51单片机作为主控&#xff0c;用数码管作为显示模块&#xff0c;按下按键K1后可进行频率测量并显示 仿真运行视频 Proteus仿真--数码管显示的频率计 附完整Pro…

Vue + Element UI 实现复制当前行数据功能及解决复制到新增页面组件值不更新的问题

文章目录 引言第一部分&#xff1a;复制当前行数据功能的实现1.1 环境准备1.2 创建表格并渲染数据1.3 解决复制的数据不更新问题 第二部分&#xff1a;拓展知识2.1 Vue的响应性原理2.2 Element UI的更多用法 结语 Vue Element UI 实现复制当前行数据功能及解决复制到新增页面组…

「C++」入门

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;C启航 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 文章目录 &#x1f349;前言&#x1f349;命名空间&#x1f34c;访问命名空间中的元素&#x1f34c;同名命名空间&#x1f34c;展开&…

SAP smartforms二维码输出

此方法需要SAP_BASIS版本在731以上 TCODE-SE73 选择’系统条形码’点击 ‘更改’ 按步骤创建一个系统条形码 Module Size 调节二维码的尺寸 进入smartforms 创建样式 填入条形码名称 创建一张表单测试二维码&#xff0c;填入创建好的样式 测试结果&#xff1a;

显示器校准软件BetterDisplay Pro mac中文版介绍

BetterDisplay Pro mac是一款显示器校准软件&#xff0c;可以帮助用户调整显示器的颜色和亮度&#xff0c;以获得更加真实、清晰和舒适的视觉体验。 BetterDisplay Pro mac软件特点 - 显示器校准&#xff1a;可以根据不同的需求和环境条件调整显示器的颜色、亮度和对比度等参数…

Ansible的重用(include和import)

环境 管理节点&#xff1a;Ubuntu 22.04控制节点&#xff1a;CentOS 8Ansible&#xff1a;2.15.6 重用 Ansible提供四种可重用的工件&#xff1a; variable文件&#xff1a;只包含变量的文件task文件&#xff1a;只包含task的文件playbook&#xff1a;可包含play、变量、ta…

***Linux常用命令及解释

1、查看Linux的版本信息 1.1、uname -a 1.2、cat /etc/issue 1.3、cat /proc/version 1.4、hostnamectl 通过使用hostnamectl命令&#xff0c;可以查询和更改系统主机名&#xff0c;并且还可以查看Linux的发行版和内核版本。 2、删除文件 3、修改目录权限 4、解压文件 5、…

vue3(二)-基础入门

一、列表渲染 of 和 in 都是一样的效果 html代码&#xff1a; <div id"app"><ul><li v-for"item of datalist">{{ item }}</li></ul><ul><li v-for"item in dataobj">{{ item }}</li></u…

【教学类-06-10】20231125(55格版)X-Y之间“乘法×题”(以1-9乘法口诀表为例)(随机抽取和正序抽取)

图片展示 &#xff08;随机打乱排序&#xff09; 正序&#xff08;每张都一样&#xff09; 背景需求&#xff1a; 2023年11月24日&#xff0c;准备了一些题目&#xff0c;分别给大4班孩子介绍“5以内加法、5以内减法、5以内加减混合”““10以内加法、10以内减法、10以内加减…

数据结构 / 结构体字节计算

1. 结构体的存储 结构体各个成员的地址是连续的结构体变量的地址是第一个成员的地址 2. 64位操作系统8字节对齐 结构体的总字节大小是各个成员字节的总和&#xff0c;字节的总和需要是最宽成员的倍数结构体的首地址是最宽成员的倍数结构体各个成员的偏移量是该成员字节的倍数…

burpsuite的大名早有耳闻,近日得见尊荣,倍感荣幸

问题&#xff1a; burpsuite中文乱码何解&#xff1f; burpsuite 与君初相识&#xff0c;犹如故人归。 burpsuite早有耳闻&#xff0c;近日得见真容&#xff0c;果然非同凡响。 Burp Suite is a comprehensive suite of tools for web application security testing. burp …

C编译过程

寻觅GCC 如果你已经安装了Clion&#xff0c;那么gcc就在根目录下。 如果没有&#xff0c;那么需要去minGW的官网下载安装。添加到环境变量中。 编写C代码 #include <stdio.h>#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0]) static int a 123;int main() {int i 0;c…

2、Burp使用

文章目录 一、为Firefox浏览器安装数字证书二、利用Intruder模块进行暴力破解 一、为Firefox浏览器安装数字证书 &#xff08;1&#xff09;利用Firefox浏览器访问http://burp或127.0.0.1:<监听端口>&#xff0c;点击页面右上侧的“CA Certificate”处下载CA证书&#xf…

【UCAS自然语言处理作业二】训练FFN, RNN, Attention机制的语言模型,并计算测试集上的PPL

文章目录 前言前馈神经网络数据组织Dataset网络结构训练超参设置 RNN数据组织&Dataset网络结构训练超参设置 注意力网络数据组织&Dataset网络结构Attention部分完整模型 训练部分超参设置 结果与分析训练集Loss测试集PPL 前言 本次实验主要针对前馈神经网络&#xff0…

不同品牌的手机可以则哪一个你投屏到电视?

如果你使用AirDroid Cast的TV版&#xff0c;苹果手机可以通过airPlay或无线投屏方式&#xff0c;将屏幕同步到电视屏幕&#xff1b;多个品牌的安卓手机可以通过无线投屏投射到电视。而且无线投屏不限制距离&#xff0c;即使是远程投屏也可以实现。 打开AirDroid Cast的TV版&…

鸿蒙(HarmonyOS)应用开发——装饰器

简介 ArkTS是HarmonyOS优选的主力应用开发语言。它在TypeScript&#xff08;简称TS&#xff09;的基础上&#xff0c;扩展了声明式UI、状态管理等相应的能力&#xff0c;让开发者可以以更简洁、更自然的方式开发高性能应用。TS是JavaScript&#xff08;简称JS&#xff09;的超…

shiro的前后端分离模式

shiro的前后端分离模式 前言&#xff1a;在上一篇《shiro的简单认证和授权》中介绍了shiro的搭建&#xff0c;默认情况下&#xff0c;shiro是通过设置cookie&#xff0c;使前端请求带有“JSESSION”cookie&#xff0c;后端通过获取该cookie判断用户是否登录以及授权。但是在前…

【开源】基于Vue和SpringBoot的木马文件检测系统

项目编号&#xff1a; S 041 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S041&#xff0c;文末获取源码。} 项目编号&#xff1a;S041&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 木马分类模块2.3 木…