Selenium 自动化测试框架 API 详解

Selenium webUI 自动化测试框架

前言:Selenium 框架是专门针对 webUI 进行测试的,在测试前需要将环境变量和依赖都安装好(传送门)。
测试起手式:

private static void test2() throws InterruptedException {
        // 创建驱动
        WebDriver webDriver = new ChromeDriver();
        // 打开百度
        webDriver.get("https://www.baidu.com");
        // 通过 css 选择器找到百度输入框
        WebElement element = webDriver.findElement(By.cssSelector("#kw"));
        // 在百度搜索框输入内容
        element.sendKeys("江边鸟");
        // 通过 css 选择器找到搜索按钮 并点击搜索
        sleep(3000);
        ;
        //webDriver.findElement(By.cssSelector("#su")).submit();
        // 在输入框中清除 江边鸟
        sleep(3000);
        webDriver.findElement(By.cssSelector("#kw")).clear();
    }

涉及 API:

  1. WebDriver new ChromeDriver(): 用于创建一个驱动,Selenium 框架操控浏览器是通过驱动作为中间介进行操控的(上文说到过);
  2. webDriver.get():用于将 Chrome 浏览器打开并指向到哪个网页;参数用于输入一个网页
  3. webDriver.findElement()要找的元素在哪,参数为 By.cssSelector(“”) 或者 By.xpath(“”),两个都为选择器,用于对网页上的便签元素进行指定,前者为 css 选择器,后置为 xpath 选择器
  4. WebElement.sendKeys(“”)对找到的元素进行输入操作,参数为想要输入的内容
  5. webDriver.findElement(By.cssSelector(“”)).click():对选中的元素执行点击事件
  6. webDriver.findElement(By.cssSelector(“”)).clear():对选中的元素执行清除事件

补充(对于两种选择器如何找到对应选择器的标签):

  1. css 选择器语法

    • id 选择器使用 # 号加 id 名进行选择;例如指定百度的搜索框,其 id = “kw” ,如下图
      在这里插入图片描述

    这样我们就可以通过 #kw 来指定到百度的搜索框上
    在这里插入图片描述

    • 类选择器:使用 . 加 class 名进行选择。例如通过类选择器指定百度搜索框:
      在这里插入图片描述

      即通过 .s_ipt 指定到百度搜索框
      在这里插入图片描述

    • 标签选择器:通过标签名直接进行选择。依然选择百度搜索框:

      在这里插入图片描述

    • 后代选择器在标签后面继续加元素即可(父级选择器 子级选择器)。选择百度搜索框:

      在这里插入图片描述

  2. xpath 选择器语法

    • 绝对路径:/…/… (不常用)效率非常低。类似于下面这种:
      在这里插入图片描述

    • 相对路径(常见/常用)都以 // 开头,以 / 分割,以下以选择百度搜索框为例

      • 相对路径+索引:索引是从1开始,不写索引默认为1;
        在这里插入图片描述

      • 相对路径+属性值标签名[@属性名="值"]
        在这里插入图片描述

      • 相对路径+通配符使用 * 代表所有 路径/标签 下,进行寻找

        在这里插入图片描述

      • 相对路径+文本匹配 通过 text() = "文本内容",来确定元素位置。例如找到百度页面中的 新闻 :
        在这里插入图片描述
        在这里插入图片描述

Selenium 测试的方法用例

这里会对 Selenium 自动化测试的常用方法进行一一举例并说明

操作测试对象的方法

这里的方法也就是上面起手式的方法:click(),clear(),sendKeys(),submit()

  1. click():方法点击事件,即对指定的元素进行点击(无局限性);
  2. clear():清除指定元素中的内容
  3. sendKeys():针对输入框,在输入框中输入内容
  4. submit():和 click() 作用一样,但局限于只能在 form 标签下选择才起作用,别的标签中会报错

举例:打开谷歌浏览器,进入百度搜索页面,在百度输入框中输入 “江边鸟”,并进行搜索;再清除输入框中的 “江边鸟”:
打开浏览器,进入百度搜索,输入 江边鸟:
在这里插入图片描述
进行搜索,搜索完清除输入内容:
在这里插入图片描述

private static void test2() throws InterruptedException {
        // 创建驱动
        WebDriver webDriver = new ChromeDriver();
        // 打开百度
        webDriver.get("https://www.baidu.com");
        // 通过 css 选择器找到百度输入框
        WebElement element = webDriver.findElement(By.cssSelector("#kw"));
        // 在百度搜索框输入内容
        element.sendKeys("江边鸟");
        // 通过 css 选择器找到搜索按钮 并点击搜索
        sleep(3000);  // 等待3秒。强制睡眠,后面会提到
        webDriver.findElement(By.cssSelector("#su")).click();
        //webDriver.findElement(By.cssSelector("#su")).submit();
        // 在输入框中清除 江边鸟
        sleep(3000);
        webDriver.findElement(By.cssSelector("#kw")).clear();
    }

补充:getAttribute() 方法:用于找到指定按钮的值
举例: 通过 getAttribute() 方法找到 #su css选择器的值,预期结果是百度一下。

private static void test3() {
       
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("https://www.baidu.com");
        String button_value = webDriver.findElement(By.cssSelector("#su")).getAttribute("value");  // 通过getAttribute() 方法找到 按钮的值
        if (button_value.equals("百度一下")){
            System.out.println(button_value);
            System.out.println("测试通过");
        }else {
            System.out.println(button_value);
            System.out.println("测试不通过");
        }
    }

在这里插入图片描述

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

添加等待的方法

  1. 强制等待 sleep() :sleep(等待时间),单位为毫秒。必须等待指定的时间才会执行后面的代码。
    在这里插入图片描述

  2. 隐式等待 timeouts().implicitlyWait(参数1, 参数2):该方法设置了一个全局的等待时间,适用于整个浏览器会话期间。 它等待的时间是针对页面中的所有元素,一旦页面加裁完成,等侍就会结束。如果在设置的时间内找不到元素,则抛出NoSuchElementException 异常。 简言之:当代码执行完了的时候,隐式等待下面的代码就会立即执行,当前面没有执行完的时候,隐式等待就不会执行,即隐式等待最多等待时长为设定的参数值。 参数1 为等待时长,参数2为时长单位(秒,分,小时,天)

举例:打开谷歌浏览器,进入百度搜索页面,在百度输入框中输入 “江边鸟”,强制等待3秒进行搜索;隐式等待3天再清除输入框中的 “江边鸟”:

private static void test4() throws InterruptedException {  // 强制等待 sleep() 和 隐式等待 webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.DAYS) 其中第一个参数指的是等待时长,第二个参数是时长单位(秒,分,小时,天)
        // 隐式等待和强制等待的区别:
        //      隐式等待:当前面执行完了的时候,隐式等待下面的代码就会立即执行,当前面没有执行完的时候,隐式等待就不会执行,即隐式等待最多等待时长为设定的参数值
        //      强制等待:必须等待完设置的时间后面代码才能执行
        // 创建驱动
        
        WebDriver webDriver = new ChromeDriver();
        // 打开百度
        webDriver.get("https://www.baidu.com");
        // 通过 css 选择器找到百度输入框
        WebElement element = webDriver.findElement(By.cssSelector("#kw"));
        // 在百度搜索框输入内容
        element.sendKeys("江边鸟");
        // 通过 css 选择器找到搜索按钮 并点击搜索
        sleep(3000);  // 强制等待
        webDriver.findElement(By.cssSelector("#su")).click();
        //webDriver.findElement(By.cssSelector("#su")).submit();
        // 在输入框中清除 江边鸟
        long began = System.currentTimeMillis();  // 记录时间,用于计算隐式等待具体时间
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.DAYS);   // 隐式等待
        webDriver.findElement(By.cssSelector("#kw")).clear();
        long end = System.currentTimeMillis();
        System.out.println("隐式等待实际等待时间: " + (end - began));
    }

在这里插入图片描述

执行结果:会立即清除输入框中的内容,而不会真的等待三天。

  1. 显示等待 WebDriverWait类用于显式等待条件的实现,这个类允许在一定的时间范围内等待某个条件的成立(例如元素是否存在、是否可见、是否可点击等),从而避免由于页面加载或动态内容渲染不完全而导致的错误。
    • 使用两个参数的构造方法时: 在这里插入图片描述
      timeOutInSeconds : 等待最大时间,单位为秒,如果在这段时间内条件未满足,WebDriverWait 会抛出 TimeoutException 异常。
    • 使用三个参数的构造方法时:
      在这里插入图片描述

例如:判断百度搜索页面中,新闻这个按钮是否可以点击
在这里插入图片描述在这里插入图片描述

private static void test6() { // 显式等待: 即等待的是条件
        // 隐式等待和显式等待的区别:隐式等待等待的是整个页面,当整个页面加载完才执行等待语句下面的代码,当等待时间等待完整个页面还没有加载出来的话,就会报错;时间单位可以自己选择
        // 显式等待:等待的是条件,时间单位是秒; 对要判断的条件等待若干秒,若干秒之后还没有满足条件就会抛出 TimeoutException 异常
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("https://www.baidu.com");
        WebDriverWait webDriverWait = new WebDriverWait(webDriver,3);  // 显式等待 单位是秒; 对要判断的条件等待3秒,若3秒之后还没有满足条件就会抛出 TimeoutException 异常
        webDriverWait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#s-top-left > a:nth-child(1)"))); //  判断元素是不是可以点击

    }

可以看到代码正常退出:
在这里插入图片描述
当判断一个不可点击的标签时,就会报错(超时):

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

打印信息的方法

  1. 打印 URL :通过 *WebDriver.getCurrentUrl()* 方法。返回值是 String 类型。
  2. 打印 Title :通过 WebDriver.getTitle() 方法。返回值是 String 类型。

用例:测试一下百度的网址和百度的 Title 名。预期结果:网址(https://www.baidu.com/),Tile(百度一下,你就知道)。

private static void test5() {  // 打印网站的 URL 和 Title
       
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("https://www.baidu.com");
        String url = webDriver.getCurrentUrl();
        String title = webDriver.getTitle();
        if (url.equals("https://www.baidu.com/") && title.equals("百度一下,你就知道")){
            System.out.println("测试通过");
            System.out.println("测试网站是: " + url + ", 网站标题是: " + title);;
        }else {
            System.out.println("测试不通过");
        }
    }

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

针对浏览器操作的方法

  1. 浏览器后退:WebDriver.navigate().back()
  2. 浏览器前进:WebDriver.navigate().forward()
  3. 浏览器刷新:WebDriver.navigate().refresh()
  4. 浏览器最大化:WebDriver.manage().window().maximize()
  5. 浏览器全屏:WebDriver.manage().window().fullscreen()
  6. 自定义浏览器大小:WebDriver.manage().window().setSize(new Dimension(参数1,参数2));其中参数1代表自定义宽度,参数2代表自定义高度;
  7. 浏览器滚动条操作:((JavascriptExecutor)WebDriver).executeScript("参数");在这里浏览器的滚动条需要依靠js 脚本(在使用脚本的同时需要对类型进行强转 ),参数如下:
    • 将浏览器滚动条滑到最顶端:document.documentElement.scrollTop=0
    • 将浏览器滚动条滑到最低端:document.documentElement.scrollTop=10000

浏览器中通过 js 脚本进行控制:
在这里插入图片描述
用例:在百度搜索框中输入 电脑,并点击搜索,对搜索出来的页面执行上述所有操作;

private static void test7() throws InterruptedException { // 对浏览器进行前进,后退,刷新操作。  对浏览器滚动条进行操作,将浏览器最大化,全屏,自定义大小
        // 创建驱动
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("https://www.baidu.com");
        // 搜索
        webDriver.findElement(By.cssSelector("#kw")).sendKeys("电脑"); // 在输入框中输入 电脑
        sleep(3000);  // 强制睡眠3秒
        webDriver.findElement(By.cssSelector("#su")).click();  // 点击搜索
        // 等待3秒,浏览器后退
        sleep(3000);
        webDriver.navigate().back();
        // 等待三秒,浏览器前进
        sleep(3000);
        webDriver.navigate().forward();
        // 等待三秒,浏览器刷新
        sleep(3000);
        webDriver.navigate().refresh();
        // 等待三秒,对浏览器滚动条进行操作
        ((JavascriptExecutor)webDriver).executeScript("document.documentElement.scrollTop=10000");  // 首先这里的操作通过 Js 执行,所以要先将 webDriver 强转成 Js ,
        // 然后通过 Js 代码来操控滚动条,让滚动条下滑到最下面
        // scrollTop = 10000 , 指的是让滚动条下滑到末尾,而 = 0 的时候,是滑到顶端
        /*
        *  等待三秒,让浏览器最大化
        * */
        sleep(3000);
        webDriver.manage().window().maximize();
        // 等待三秒,让浏览器全屏
        sleep(3000);
        webDriver.manage().window().fullscreen();
        // 等待三秒,自定义浏览器大小
        sleep(3000);
        webDriver.manage().window().setSize(new Dimension(700,1300));
    }
这里一系列操作的浏览器执行过程就不进行截图了(截图没法展示完整的效果),感兴趣的话可以复制代码自己运行下

键盘事件方法

sendKeys(Keys.组合键1,"组合键2"):组合键1指的是例如 CONTROL,ALT,TAB等等这些键,组合键2指的是 “A”,“X”,“C”,"V"等等这些键;
源码如下:
在这里插入图片描述

用例:在百度搜索框中输入 发发发 ,然后执行 CONTROL+A,CONTROL+X,CONTROL+V;

private static void test8() throws InterruptedException { // 键盘操作事件
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("https://www.baidu.com");
        // 搜索
        webDriver.findElement(By.cssSelector("#kw")).sendKeys("发发发发"); // 在输入框中输入 发发发发
        // 等待三秒,执行 Control + a
        sleep(3000);
        webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"A");  // 其中 Control + a 等都是对搜索框中的内容进行操作的
        // 等待三秒,执行 Control + x
        sleep(3000);
        webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"X");
        // 等待三秒,执行 Control + v
        sleep(3000);
        webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"V");
    }

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

鼠标点击事件

Actions.moveToElement(指定要被点击的元素).点击方式.perform():在 Actions 类中,需要先指定一个被点击的元素,然后通过点击方式进行点击,perform() 用于将点击后的结果显示出来;
点击方式(常见):

  1. click(),click(WebElement onElement) :左键单击
  2. contextClick(),contextClick(WebElement onElement) :右击
  3. doubleClick(), doubleClick(WebElement onElement) :双击
  4. dragAndDrop(WebElement source,WebElement target):拖动,将 source 元素 拖动到 target 的位置
  5. moveByOffset(int xOffset, int yOffset)、moveToElement(WebElement toElement)、moveToElement(WebElement toElement, int xOffset, int yOffset):移动

用例:

  1. 单击
WebDriver webDriver = new ChromeDriver();
Actions action = new Actions(webDriver);
action.click().perform();// 鼠标左键在当前停留的位置进行单击操作 
action.click(driver.findElement(By.选择器)).perform();// 鼠标左键点击指定的元素
  1. 右击
WebDriver webDriver = new ChromeDriver();
Actions action = new Actions(webDriver);
action.contextClick().perform();// 鼠标右键在当前停留的位置进行单击操作 
action.contextClick(driver.findElement(By.选择器)).perform();// 鼠标右键点击指定的元素
  1. 双击
WebDriver webDriver = new ChromeDriver();
Actions action = new Actions(webDriver);
action.doubleClick().perform();// 鼠标在当前停留的位置进行双击操作 
action.doubleClick(driver.findElement(By.选择器)).perform();// 鼠标双击指定的元素
  1. 拖动
WebDriver webDriver = new ChromeDriver();
Actions action = new Actions(webDriver);
action.dragAndDrop(source,target).perform();// 将 source 元素拖动到 target 元素的位置。
  1. 移动
WebDriver webDriver = new ChromeDriver();
Actions action = new Actions(webDriver);
action.moveByOffset(xOffset,yOffset).perform();// 以鼠标当前位置或者 (0,0) 为中心开始移动到 (xOffset, yOffset) 坐标轴,xOffset 为横坐标,yOfferset 为纵坐标

WebElement toElement = webDriver.findElement(By.cssSelector("")); // 目标元素 
action.moveToElement(toElement).perform();// 将鼠标移到 toElement 元素中心

action.moveToElement(toElement,xOffset,yOffset).perform();// 将鼠标移到元素 toElement 的 (xOffset, yOffset) 位置,这里的 (xOffset, yOffset) 是以元素 toElement 左上角为 (0,0) 开始的 (x, y) 坐标轴。

浏览器操作补充

  1. 关闭浏览器:close() 和 quiet()close() 关闭第一个窗口,不会清理缓存;quiet() 关闭所有窗口并清理缓存;
  2. 获取浏览器新窗口句柄:WebDriver.getWindowHandles(),通常与 webDriver.switchTo().window(新窗口句柄) 转向新窗口 搭配使用。 原因:当页面转到另一个页面时,此时程序还控制的是之前的页面,而不会对新的页面进行控制,所有需要通过代码让程序转向到控制新的页面
  3. 对浏览器页面进行截图操作:WebDriver.getScreenshotAs(输出类型)

用例:

  1. 关闭浏览器:
WebDriver webDriver = new ChromeDriver();
webDriver.close();
//        webDriver.quit();

  1. 获取浏览器新窗口句柄:
private static void test2() throws InterruptedException {  // 获取新窗口的句柄;   当浏览器重新跳转到新窗口的时候,需要加载新窗口的句柄,才能在新窗口上进行操作
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("https://www.baidu.com/");
        webDriver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();  // 点击新闻
        Set<String> handles = webDriver.getWindowHandles(); // 获取新窗口句柄
        String aim = "";
        for (String handle: handles) {
            aim = handle;
        }
        webDriver.switchTo().window(aim);  // 转向新的窗口
        sleep(2000);
        webDriver.findElement(By.cssSelector("#ww")).sendKeys("黑神话悟空");  // 在新闻搜索框中输入黑神话悟空
        sleep(2000);
        webDriver.findElement(By.cssSelector("#s_btn_wr")).click(); // 点击进行搜索
    }

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

  1. 截图操作
private static void test3() 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();
        sleep(2000);
        // 进行截图
        File file = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);   // 以文件内容输出
        FileUtils.copyFile(file,new File("E://Screenshot.png"));  // 将上述文件放到 E 盘中
    }

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

定位一组元素

通过 WebDriver.findElements(选择器)来进行实现,例如勾选某个页面的多个复选框:

private static void Page1() {  // 将复选框勾选,单选框不进行任何操作
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("http://localhost:63342/TestClass/SeleniumTest/page/test01.html?_ijt=thp9mrlvh9h5fto6af61o491f5&_ij_reload=RELOAD_ON_SAVE"); // 这个页面是本地路径
        List<WebElement> elements = webDriver.findElements(By.cssSelector("input"));   // 针对 input 标签进行查找
        for (int i = 0; i < elements.size(); i++) {
            // getAttribute 用于获取页面上元素的属性值,里面的 type 是当前元素的属性值
            if (elements.get(i).getAttribute("type").equals("checkbox")){
                elements.get(i).click();  // 进行点击
            }else {
                // 啥也不做
                ;
            }
        }
    }

在这里插入图片描述

层级定位

用例:找到 click 并点击,结构如下:
在这里插入图片描述

private static void Page2() throws InterruptedException {  //  点击 iframe 标签中的 click 事件
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("http://localhost:63342/TestClass/SeleniumTest/page/test02.html?_ijt=4ldrcatf1t651duqj4b7kdpnie&_ij_reload=RELOAD_ON_SAVE");
        // 指定 id 为 f1 的 iframe 标签
        webDriver.switchTo().frame("f1"); // 对于 iframe 标签需要指定事件是在哪个 iframe 标签中。  参数为 iframe 标签的 id
        sleep(2000);
        webDriver.findElement(By.cssSelector("body > div > div > a")).click();  // 执行点击事件
    }

在这里插入图片描述

下拉框处理

通过 Select.selectBy方法()进行查找:

  1. select.selectByValue(String value):通过标签里面的 Value 值来进行查找;
  2. select.selectByIndex(int index);:通过 index 来进行查找;
  3. selectByVisibleText(String text):通过匹配到的可见字符来进行查找,其中 text 值就是页面下拉框肉眼看到的选项

用例:
在这里插入图片描述
在这里插入图片描述

    private static void Page3() {  // 针对下拉框的操作  
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("http://localhost:63342/TestClass/SeleniumTest/page/test03.html?_ijt=uu5ud0k9q45om9jks54c33jj6h&_ij_reload=RELOAD_ON_SAVE");
        WebElement webElement = webDriver.findElement(By.cssSelector("#ShippingMethod"));
        Select select = new Select(webElement);
        select.selectByValue("8.34");   // 根据 value 查找,找到值为 8.34 的下拉框

    }

在这里插入图片描述

针对 alert 框进行操作

  1. 取消 alert 弹窗:WebDriver.switchTo().alert().dismiss()
  2. 点击弹窗:WebDriver.findElement(By.cssSelector("button")).click()
  3. 在弹窗中输入内容:WebDriver.switchTo().alert().sendKeys("")
  4. 确认弹窗中的内容:WebDriver.switchTo().alert().accept()

用例:对 alert 框/弹窗 执行上述所有操作
在这里插入图片描述

private static void Page4() throws InterruptedException { //    实现 alert 框中的输入,点击,确认,取消事件
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("http://localhost:63342/TestClass/SeleniumTest/page/test04.html?_ijt=fgvn5ms2fav9ieesu6d12lekcs&_ij_reload=RELOAD_ON_SAVE");
        webDriver.findElement(By.cssSelector("button")).click();
        sleep(2000);
        // alert 弹窗取消
        webDriver.switchTo().alert().dismiss();
        sleep(2000);
        // 点击 alert
        webDriver.findElement(By.cssSelector("button")).click();
        sleep(2000);
        // 在 alert 弹窗中输入内容
        webDriver.switchTo().alert().sendKeys("alert 输入框");
        sleep(2000);
        // 对输入的内容进行确认
        webDriver.switchTo().alert().accept();
    }

在这里插入图片描述

实现文件上传

WebDriver.findElement(By.cssSelector("")).sendKeys("文件目录") 通过send_keys 添加本地文件路径就可以了。绝对路径和相对路径都可以,关键是上传的文件存在。
用例:将电脑中的任意文件进行上传
在这里插入图片描述

private static void Page5() { //   实现文件的上传
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("http://localhost:63342/TestClass/SeleniumTest/page/test05.html?_ijt=gitonvvonlr9avqffkoprbkilu&_ij_reload=RELOAD_ON_SAVE");
        webDriver.findElement(By.cssSelector("input")).sendKeys("C:\\Users\\lenovo\\Pictures\\Camera Roll");  // 上传本地文件
    }

在这里插入图片描述

总结即目录,创作不易,若对您有所帮助那就点个赞呗!!!

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值