Python_Selenium自动化测试详细教程

这篇具有很好参考价值的文章主要介绍了Python_Selenium自动化测试详细教程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

   Python Selenium是Selenium WebDriver的Python语言封装,为Python开发者提供了一个方便易用的自动化测试库。它支持多种浏览器(如Chrome、Firefox、Edge等)以及多个操作系统,可以模拟用户在浏览器中的各种行为,包括打开网页、查找元素、输入文本、点击链接、提交表单、上传文件等。

  • Python+Selenium 来实现的web端自动化, 以下演示会用到禅道、百度、京东和自己编写的html.

一、准备工作

1、安装

  • 安装Python 3
  • 安装selenium库,命令:pip install selenium
  • 搭建禅道环境

2、导入浏览器驱动

selenium操作不同的浏览器,需要下载不同浏览器的驱动


  • Firefox 浏览器驱动: 浏览器驱动下载 webdriver.Firefox()
  • Chrome浏览器驱动:浏览器驱动下载 webdriver.Chrome()
  • IE浏览器驱动:浏览器驱动下载 webdriver.Ie()
  • Edge浏览器驱动:浏览器驱动下载 webdriver.Edge()

以chrome浏览器为例:
1、进入到下载页面,找到符合自己浏览器版本的驱动
2、下载好了之后,右键解压到当前文件夹
3、将得到的chromedriver.exe放到Python的安装目录
python自动化selenium,# Selenium 模块,python,selenium,chrome

二、使用方法

from selenium import webdriver
from selenium.webdriver.common.by import By
import time


class SampleTutorial:

    def __init__(self):
        # 创建了一个Chrome浏览器的WebDriver实例
        self.driver = webdriver.Chrome()
        # ChromeOptions类提供了对Chrome浏览器各种选项进行配置的方法;
        # 在excludeSwitches参数中,将enable-logging指定为要排除的选项,表示不启用浏览器的日志功能
        # options = webdriver.ChromeOptions()
        # options.add_experimental_option('excludeSwitches', ['enable-logging'])
        # self.drive = webdriver.Chrome(options=options)
        # 最大化窗口
        self.driver.maximize_window()
        # 隐式等待,设置最大的等待时长,只对查找元素(find_elementXXX)生效
        self.driver.implicitly_wait(2)

    def method(self):
        """代码执行"""
        # 通过get()方法打开网页
        self.driver.get('http://192.168.100.210/zentao/')

    def sign_out(self):
        """退出浏览器"""
        # 关闭当前浏览器窗口或标签页。如果只有一个窗口或标签页被打开,调用driver.close()将会关闭整个浏览器会话。
        # 如果有多个窗口或标签页存在,调用driver.close()将关闭当前活动窗口或标签页,并切换到上一个窗口或标签页。
        self.driver.close()
        # 关闭浏览器,调用driver.quit()会终止WebDriver对象的相关进程和资源,及时清理测试环境。
        self.driver.quit()


if __name__ == "__main__":
    run = SampleTutorial()
    run.method()
    # 当自动化测试脚本执行完毕后,WebDriver对象会自动关闭相关的浏览器进程,释放资源并终止与浏览器的会话。
    # 但是,有时候在测试过程中,脚本出现异常导致未关闭浏览器,这时我们就需要手动调用来关闭浏览器。
    # run.sign_out()

1、元素定位方法

  • 禅道登陆演示
    python自动化selenium,# Selenium 模块,python,selenium,chrome
图一

python自动化selenium,# Selenium 模块,python,selenium,chrome

图二

  • 单属性查找
    def method(self):
        """代码执行"""
        # 通过get()方法打开网页
        self.driver.get('http://192.168.100.210/zentao/')

        # 1.用 id 属性定位查找
        self.driver.find_element(By.ID, "account")

        # 2.用 name 属性定位查找
        self.driver.find_element(By.NAME, "account")

        # 3.用 class 属性定位查找
        self.driver.find_element(By.CLASS_NAME, "form-control")

        # 4.用 xpath 属性定位查找
        self.driver.find_element(By.XPATH, '//*[@id="account"]')

        # 5.具有给定标签名称的第一个元素将被返回
        self.driver.find_element(By.TAG_NAME, "input")

        # 6.用 css 属性定位查找
        # 方法一[标签名]
        self.driver.find_element(By.CSS_SELECTOR, 'input')
        # 方法二[id], #代表id
        self.driver.find_element(By.CSS_SELECTOR, '#account')
        # 方法三[class], .代表class
        self.driver.find_element(By.CSS_SELECTOR, '.form-control')
        # 方法四[其他属性]
        self.driver.find_element(By.CSS_SELECTOR, '[name="account"]')

        # 7.链接文本值与位置匹配的第一个元素将被返回
        # (通过标签对之间的文本进行定位)
        self.driver.find_element(By.LINK_TEXT, "忘记密码")

        # 8.具有部分链接文本值与位置匹配的第一个元素将被返回
        # (partial link其实是对link的一个扩展,因为有些时候链接文本很长,这时候就可以使用其中的一部分来进行定位)
        self.driver.find_element(By.PARTIAL_LINK_TEXT, "忘记")
  • 组合属性查询
    def method(self):
        """代码执行"""
        # 1.通过get()方法打开网页
        self.driver.get('http://192.168.100.210/zentao/')

        # 2.标签名和id属性值组合定位
        self.driver.find_element(By.CSS_SELECTOR, 'input#account')

        # 3.标签名和class属性值组合定位
        self.driver.find_element(By.CSS_SELECTOR, 'input.form-control')

        # 4.标签名和属性(含属性值)组合定位
        self.driver.find_element(By.CSS_SELECTOR, 'input[name="account"]')

        # 5.多个属性组合定位
        self.driver.find_element(By.CSS_SELECTOR, '[class="form-control"][name="account"]')
  • 层级查询
    python自动化selenium,# Selenium 模块,python,selenium,chrome
图三
    def method(self):
        """代码执行"""
        # 通过get()方法打开网页
        self.driver.get('http://192.168.100.210/zentao/')

        # 1.查询元素时,我们也可以先查询父级,然后再查询子级,父级和子级用空格隔开,如上图所示(div - table - input)
        self.driver.find_element(By.CSS_SELECTOR, '.col-8 [class="table table-form"] #account')

  • 相同元素定位
    python自动化selenium,# Selenium 模块,python,selenium,chrome
图四
    def method(self):
        """代码执行"""
        # 通过get()方法打开网页
        self.driver.get('http://192.168.100.210/zentao/')

        # 定位第一个元素
        self.driver.find_element(By.CSS_SELECTOR, '[class="form-control"]')

        # 定位第二个元素,find_elements后面加了s
        self.driver.find_elements(By.CSS_SELECTOR, '[class="form-control"]')[1]

  • 我们在进行元素定位时,获取到的元素一定是唯一的或第一个。查看是否唯一我们可以按CTRL+F搜索,如下:

python自动化selenium,# Selenium 模块,python,selenium,chrome

2、输入、清空、点击操作

    def method(self):
        """代码执行"""
        # 通过get()方法打开网页
        self.driver.get('http://192.168.100.210/zentao/')

        # 输入:send_keys()
        self.driver.find_element(By.CSS_SELECTOR, '#account').send_keys("admin")

        # 清空: clear()
        self.driver.find_element(By.CSS_SELECTOR, '#account').clear()

        # 单机操作(相当于鼠标点击):click()
        self.driver.find_element(By.CSS_SELECTOR, '.form-actions #submit').click()

3、回车键操作

# 点击登录按钮,一般情况下,使用click()进行点击
# 有些时候也可以使用submit()代替click(),相当于敲回车
    def method(self):
        """代码执行"""
        # 通过get()方法打开网页
        self.driver.get('https://www.baidu.com/')

        # 输入内容,点击百度一下
        self.driver.find_element(By.CSS_SELECTOR, '[class="s_ipt"]').send_keys("软件测试")
        # 回车操作(相当于按回车键):submit()
        self.driver.find_element(By.CSS_SELECTOR, '[id="su"]').submit()

4、获取元素内容

  • Text获取元素内容

python自动化selenium,# Selenium 模块,python,selenium,chrome

# text 获取元素内容
text = self.driver.find_element(By.CSS_SELECTOR, '.form-actions a').text
print(text)

# 结果:忘记密码
  • 如果使用Text获取元素内容时,返回的是空值,但未报错,这个时候我们需要使用get_attribute(‘innerText’)获取元素的内容
    python自动化selenium,# Selenium 模块,python,selenium,chrome
# 获取元素内容
get = self.driver.find_element(By.CSS_SELECTOR, '#loginPanel h2').get_attribute('innerText')
print(get)

# 结果:易软天创项目管理系统

5、获取元素属性的值

  • 禅道登陆演示

python自动化selenium,# Selenium 模块,python,selenium,chrome

# 获取属性的值
get = self.driver.find_element(By.CSS_SELECTOR, '[id="keepLoginon"]').get_attribute('title')
print(get)

# 结果:保持登录

6、元素判断

  • 没有演示环境,就自己写一个html页面

在页面中显示元素:
python自动化selenium,# Selenium 模块,python,selenium,chrome

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>演示数据</title>
</head>
<body>
      <form>
            <input type="text" value="用户名" id="account"><br>
			<input type="password" value="密码" id="password"><br>
        </form>
</body>
</html>

在页面中不显示元素:
python自动化selenium,# Selenium 模块,python,selenium,chrome

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>演示数据</title>
</head>
<body>
      <form>
          <input style="visibility: hidden;" type="text" value="用户名" id="account"><br>
	      <input type="password" value="密码" id="password"><br>
        </form>
</body>
</html>

禁用输入框:
python自动化selenium,# Selenium 模块,python,selenium,chrome

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>演示数据</title>
</head>
<body>
      <form>
          <input disabled="disabled" type="text" value="用户名" id="account"><br>
	      <input type="password" value="密码" id="password"><br>
      </form>
</body>
</html>

1、is_displayed()

1、is_displayed():判断元素是否存在,结果是真或假
1-1显示元素,在HTML里,在页面也显示,返回True1-2隐藏元素,在HTML里,不在页面显示,返回Flase
1-3不在HTML里,不存在这个元素,会报错

# 判断输入框是否在页面中显示
drive = self.driver.find_element(By.CSS_SELECTOR, '#account').is_displayed()
print(f"元素是否显示:{drive}")

2、is_enabled()

is_enabled():判断是否可用
# 判断输入框是否可以输入
drive = self.driver.find_element(By.CSS_SELECTOR, '#account').is_enabled()
print(f"输入框是否可以输入:{drive}")

3、is_selected()

  • 禅道登陆页面演示
is_selected():判断是否选中,一般用于复选框或单选框的选中判断
# 勾选保持登陆操作
# self.driver.find_element(By.CSS_SELECTOR, '[name="keepLogin[]"]').click()
drive = self.driver.find_element(By.CSS_SELECTOR, '[name="keepLogin[]"]').is_selected()
if drive:
	print(f"已勾选:{drive}")
else:
	print(f"未勾选:{drive}")


7、iframe&frame切换

说明:在html语法中,frame 元素或者iframe元素的内部会包含一个被嵌入的另一份html文档,这个时候如果我们需要操作iframe内的文档,就需要先切换到被嵌入的文档中,才可以进行操作。

  • 禅道登陆后演示
    python自动化selenium,# Selenium 模块,python,selenium,chrome
    python自动化selenium,# Selenium 模块,python,selenium,chrome
    1.先定位到需要切换的文档 — iframe&frame
    2.切换文档(切到frame中):switch_to.frame()
    3.从子frame切回到父frame:switch_to.parent_frame()
    4.切换到最外层文档(从frame中切回主文档):switch_to.default_content()
    def method(self):
        """代码执行"""
        # 通过get()方法打开网页
        self.driver.get('http://192.168.100.210/zentao/')
        # 登陆禅道
        self.driver.find_element(By.CSS_SELECTOR, '[id="account"]').send_keys("admin")
        time.sleep(1)
        self.driver.find_element(By.CSS_SELECTOR, '[name="password"').send_keys("123456")
        time.sleep(1)
        self.driver.find_element(By.CSS_SELECTOR, '[id="submit"]').click()
        time.sleep(1)
        # 切换方法如下:
        # 方法一
        # iframe = self.driver.find_elements_by_tag_name("iframe")[0]
        # self.driver.switch_to.frame(iframe)

        # 方法二
        # self.driver.switch_to.frame(0)

        # 方法三
        iframe = self.driver.find_element(By.CSS_SELECTOR, '#appIframe-my')
        self.driver.switch_to.frame(iframe)
        time.sleep(1)
        # 点击联系人
        self.driver.find_element(By.XPATH, '//*[@id="navbar"]/ul/li[5]/a').click()
        
        # 切换到最外层表单
        self.driver.switch_to.default_content()
        time.sleep(1)
        # 点击项目
        self.driver.find_element(By.CSS_SELECTOR, '#menu [data-app="project"]').click()

8、鼠标悬停

  • 禅道登陆界面,选择语言
    python自动化selenium,# Selenium 模块,python,selenium,chrome
  • 鼠标悬停需要导入:from selenium.webdriver import ActionChains
    def method(self):
        """代码执行"""
        # 通过get()方法打开网页
        self.driver.get('http://192.168.100.210/zentao/')

        # 需要悬停的元素,悬停到语言选择框上
        hover = self.driver.find_element(By.CSS_SELECTOR, '[class="btn"]')
        # 鼠标悬停 ActionChains(浏览器).move_to_element(悬停的元素).perform() 执行操作
        ActionChains(self.driver).move_to_element(hover).perform()
        time.sleep(1)
        # 选择需要的语言
        self.driver.find_element(By.CSS_SELECTOR, '[data-value="zh-tw"]').click()

iframe切换/鼠标悬停为提高成功率,最好是在操作后sleep(1)秒文章来源地址https://www.toymoban.com/news/detail-675424.html

9、警告框处理

  • 禅道登陆演示
    python自动化selenium,# Selenium 模块,python,selenium,chrome
    警告框处理:switch_to.alert
    def method(self):
        """代码执行"""
        # 通过get()方法打开网页
        self.driver.get('http://192.168.100.210/zentao/')
        # 点击登陆
        self.driver.find_element(By.CSS_SELECTOR, '[id="submit"]').click()
        time.sleep(1)
        # 获取警告框的文本信息
        alert_msg = self.driver.switch_to.alert.text
        print(alert_msg)
        # 接受警告框 accept()
        self.driver.switch_to.alert.accept()
        # 取消警告框 dismiss()
        # self.driver.switch_to.alert.dismiss()

10、窗口切换

  • 切换窗口:switch_to.window(需要切换到的窗口)
    def page_switching(self):
        """代码执行"""
        # 打开百度
        self.driver.get('https://www.baidu.com/')
        # 搜索框输入:CSDN
        self.driver.find_element(By.CSS_SELECTOR, '[name="wd"]').send_keys("csdn")
        time.sleep(0.5)
        # 点击百度一下
        self.driver.find_element(By.CSS_SELECTOR, '[id="su"]').click()
        time.sleep(0.5)
        # 点击CSDN官网,开启新窗口,进入CSDN官网
        self.driver.find_element(By.LINK_TEXT, 'CSDN技术社区').click()
        time.sleep(3)

        # 获取当前窗口(当前句柄名称-handle)
        windows = self.driver.current_window_handle
        print(f"当前handle:{windows}")
        # 获取所有窗口(所有句柄名称-handle),以列表的形式返回过来
        all_windows = self.driver.window_handles
        print(f"所有handle:{all_windows}")

        # 切换窗口,根据所有窗口的下标来切换,窗口顺序从0开始。(此时有两个窗口,第一个百度,第二个csdn)
        self.driver.switch_to.window(all_windows[0])
        time.sleep(3)
        # 切换到最新窗口的句柄(csdn)
        self.driver.switch_to.window(all_windows[-1])

11、select标签的下拉框选择

  • 没有演示环境,就自己写一个html页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>演示数据</title>
</head>
<body>
    <select id="nr" name="wan">
        <option value="10">每页显示10条</option>
        <option value="20">每页显示20条</option>
        <option value="50">每页显示50条</option>
        <option value="100">每页显示100条</option>
    </select>
</body>
</html>
  • 首先需要先导入一个包(注意Select的S需要大写)
  • from selenium.webdriver.support.ui import Select
    def select(self):
        """代码执行"""
        # 打开本地hthl页面
        self.driver.get('file:///C:/Users/Admin/Desktop/hthl.html')
        # 需要先定位到下拉框
        elements = self.driver.find_element(By.CSS_SELECTOR, '#nr')
        # Select(需要操作下拉框).根据什么操作
        time.sleep(2)
        Select(elements).select_by_index(1)  # 根据index,下标定位,从0开始
        time.sleep(2)
        Select(elements).select_by_value('100')  # 根据value定位
        time.sleep(2)
        Select(elements).select_by_visible_text('每页显示50条')  # 根据文本定位

12、执行JavaScript脚本

  • ①在京东商品页面模拟页面上下滑动
    def jd_search(self):
        """代码执行"""
        # 通过get()方法打开网页
        self.driver.get('https://www.jd.com/')
        # 搜索框输入:python
        self.driver.find_element(By.CSS_SELECTOR, '#key').send_keys("python") 
        # 点击搜索
        self.driver.find_element(By.CSS_SELECTOR, '.search-m .button').click()
        time.sleep(1)
        # 执行JavaScript脚本,将当前页面滚动条位置滑动到最底部
        # 传入了两个参数0和document.body.scrollHeight,表示要在窗口的水平坐标为0、垂直坐标为当前页面总高度的位置处进行滑动
        # 注:在实际应用中,该代码可用于模拟用户下滑页面的操作,以加载更多内容或触发特定事件
        self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
        # 等待页面加载完成,再次滑动页面到最底部
        time.sleep(2)
        self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
        # 等待2秒,滑动到最顶部
        time.sleep(2)
        self.driver.execute_script("window.scrollTo(0, 0)")
        time.sleep(2)
  • ②点击方法和输入方法
    def positioning_method(self):
        """代码执行"""
        self.driver.get('https://www.csdn.net/')

        # 通过文本定位元素: '//*[contains(text(),"文本")]',并通过JavaScript方法点击
        element = self.driver.find_element(By.XPATH, '//*[contains(text(),"博客")]')
        self.driver.execute_script('arguments[0].click()', element)
        time.sleep(2)

        # 通过元素的属性和属性值定位元素: '//*[@元素]',并通过JavaScript方法点击
        element = self.driver.find_element(By.XPATH, '//*[@data-report-query="spm=3001.6907"]')
        self.driver.execute_script('arguments[0].click()', element)
        time.sleep(2)

        # 通过标签名和属性值定位元素: '//元素[@元素]',并通过JavaScript方法输入
        element = self.driver.find_element(By.XPATH, '//input[@class="el-input__inner"]')
        self.driver.execute_script('arguments[0].value = "软件测试";', element)
        time.sleep(2)

13、WebDriver对象的属性

  • WebDriver对象具有许多可直接使用的属性。以下是一些常用的属性:
    def get_attribute(self):
        """代码执行"""
        # 打开百度
        self.driver.get('https://www.baidu.com/')
        # 获取当前浏览器的URL
        print(self.driver.current_url)
        # 获取当前浏览器窗口的标题
        print(self.driver.title)
        # 获取当前页面的源代码
        print(self.driver.page_source)
        # 获取有关浏览器的相关信息,如浏览器名称、版本等
        print(self.driver.capabilities)
        # 获取应用程序缓存API的实例
        print(self.driver.application_cache)
        # 获取当前会话的唯一标识符
        print(self.driver.session_id)

到了这里,关于Python_Selenium自动化测试详细教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【软件测试】python+selenium自动化测试

    一、什么是自动化测试 自动化测试指软件测试的自动化,在预设状态下运行应用程序或者系统,预设条件包括正常和异常,最 后评估运行结果。将人为驱动的测试行为转化为机器执行的过程。 单元测试 java的单元测试框架是Junit,在这里不再赘述。 接口自动化 接口测试就是

    2023年04月09日
    浏览(55)
  • 自学Python+Selenium自动化测试

            俗话说的好,书读百遍不如手过一遍,而编程这东西是看书看视频一万遍都不如你自己多敲代码、写脑图、总结分享转换成自己的内容来的实在。         今天我就把最近学的(二) Selenium核心WebDriver API 简单总结一下,方便自己以后找出来看看。         一

    2024年02月05日
    浏览(38)
  • python学习-自动化测试Selenium

     自动化测试Selenium Selenium简介 第一个Selenium应用 Selenium Python API Selenium WebDriver Selenium 初始化浏览器 Selenium导航到URL Selenium定位元素 Selenium By类 Selenium WebElement类 Selenium页面交互 Selenium ActionChains Selenium鼠标操作 Selenium键盘操作 Selenium调用JavaScript Selenium等待机制 Selenium expected

    2024年01月18日
    浏览(30)
  • Python + selenium 自动化测试框架

    项目自动化测试框架设计为4层 1.基础层(通用层) 基础层: 将通用,重复性比较高的代码封装到这里。 写通用的代码的。 其他3层想要的话,就可以直接调用。 例如: 读取测试数据的代码,读取配置信息的代码;截图的代码的,定位元素的代码等等 2.功能层(页面层) 功

    2023年04月13日
    浏览(32)
  • 如何使用Python自动化测试工具Selenium进行网页自动化?

    Selenium 是一个流行的Web自动化测试框架, 它支持多种编程语言和浏览器,并提供了丰富的API和工具来模拟用户在浏览器中的行为 。 Selenium可以通过代码驱动浏览器自动化测试流程,包括页面导航、元素查找、数据填充、点击操作等。 与PyAutoGUI和AutoIt相比, Selenium更适合于处

    2023年04月09日
    浏览(90)
  • Python自动化测试之Selenium详解

    1.安装 完成自动化测试,需要配置三个东西。 selenium :pip就可以了 chrome :浏览器下载一个谷歌浏览器就行 chrome-driver :下载地址http://chromedriver.storage.googleapis.com/index.html 这里需要对应到自己的浏览器版本下载。 从浏览器上下载到本地后,本机mac上自动保存至Download/目录下

    2024年03月28日
    浏览(34)
  • Python+Selenium自动化测试详细教程

       Python Selenium是Selenium WebDriver的Python语言封装,为Python开发者提供了一个方便易用的自动化测试库。它支持多种浏览器(如Chrome、Firefox、Edge等)以及多个操作系统,可以模拟用户在浏览器中的各种行为,包括打开网页、查找元素、输入文本、点击链接、提交表单、上传文

    2023年04月18日
    浏览(37)
  • Python自动化测试利器selenium详解

    Selenium是一种常用的Web自动化测试工具,支持多种编程语言和多种浏览器,可以模拟用户的交互行为,自动化地执行测试用例和生成测试报告。Selenium基于浏览器驱动实现,结合多种定位元素的方法,可以实现各种复杂的Web应用程序的测试 自动化测试指软件测试的自动化,在

    2024年02月16日
    浏览(28)
  • Python+Selenium自动化测试项目实战

    第 1 章 自动化测试 1.1、自动化测试介绍 自动化测试就是通过自动化测试工具帮我们打开浏览器,输入网址,输入账号密码登录,及登录后的操作,总的说来自动化测试就是通过自动化测试脚本来帮我们从繁琐重复的手工测试里面解脱出来,把时间和精力花到更好的地方去,

    2023年04月17日
    浏览(34)
  • python自动化测试工具selenium

    selenium 是网页应用中最流行的自动化测试工具,可以用来做自动化测试或者浏览器爬虫等。官网地址为:Selenium。相对于另外一款web自动化测试工具QTP来说有如下优点: 免费开源轻量级,不同语言只需要一个体积很小的依赖包 支持多种系统,包括Windows,Mac,Linux 支持多种浏

    2024年02月08日
    浏览(69)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包