python selenium元素定位、alert操作、iframe切换、多窗口切换、键盘操作、鼠标操作、js操作、操作本地文件、css高级操作

用了那么久的selenium,整理一篇自己经常用到的标签和方法
本文档持续更新优化,喜欢的小伙伴可以点赞收藏一下

1. 通用元素定位方法,需要引入By.

find_element_by_id()这种定位方式已经取消,下面定位方式最新迭代

from selenium import webdriver
from selenium.webdriver.common.by import By
browser = webdriver.Chrome()
url = 'https://www.baidu.com'
browser.get(url)
btn = browser.find_element(By.ID,  element)
btn = browser.find_element(By.CSS_SELECTOR ,  element)
btn = browser.find_element(By.CLASS_NAME ,  element)
btn = browser.find_element(By.LINK_TEXT ,  element)
btn = browser.find_element(By.NAME ,  element)
btn = browser.find_element(By.PARTIAL_LINK_TEXT ,  element)
btn = browser.find_element(By.TAG_NAME ,  element)
btn = browser.find_element(By.XPATH ,  element)

2. 通用多个元素查找By

btn = browser.find_elements(By.ID,  element)
btn = browser.find_elements(By.CSS_SELECTOR ,  element)
btn = browser.find_elements(By.CLASS_NAME ,  element)
btn = browser.find_elements(By.LINK_TEXT ,  element)
btn = browser.find_elements(By.NAME ,  element)
btn = browser.find_elements(By.PARTIAL_LINK_TEXT ,  element)
btn = browser.find_elements(By.TAG_NAME ,  element)
btn = browser.find_elements(By.XPATH ,  element)

3. css_selector()的使用方法

引用css_selector

# 单个元素查找
# 1.用 标签名 定位查找
driver.find_element_by_css_selector("input")

# 2.用 id 属性定位查找 
driver.find_element_by_css_selector("kw")

# 3.用 class 属性定位查找
driver.find_element_by_css_selector("s_ipt")

# 4.其他属性定位
driver.find_element_by_css_selector("[name='wd']")

# 组合元素查找
# 1. 标签名及id属性值组合定位

driver.find_element_by_css_selector("input#kw")

# 2.  标签名及class属性值组合定位

driver.find_element_by_css_selector("input.s_ipt")

# 3. 标签名及属性(含属性值)组合定位

driver.find_element_by_css_selector("input[name="wd"]")

# 4. 标签及属性名组合定位

driver.find_element_by_css_selector("input[name]")

# 5. 多个属性组合定位

driver.find_element_by_css_selector("[class="s_ipt"][name="wd"]")

示例:
# 1. class拥有多个属性值,只匹配其中一个时
driver.find_element_by_css_selector("input[class ~= "bg"]")

# 2. 匹配以字符串开头的属性值
driver.find_element_by_css_selector("input[class ^= "bg"]")

# 3. 匹配以字符串结尾的属性值
driver.find_element_by_css_selector("input[class $= "s_btn"]")

# 4. 匹配被下划线分隔的属性值
driver.find_element_by_css_selector("input[class |= "s"]")

css高级操作

示例层级
# 1.直接子元素层级关系,如上图的 百度一下 ,input为span的直接子元素(用 > 表示)
driver.find_element_by_css_selector(".bg.s_btn_wr > input")
# class为bg和s_btn_wr 的span标签的子元素input
# 2.只要元素包含在父元素里面,不一定是直接子元素,用空格隔开,如图一所示,form 下面的 span 里面的input
driver.find_element_by_css_selector("#form input")
# id是form的form标签里面的input标签
# 3.多级关系
driver.find_element_by_css_selector("#form > span > input")
# id是form的form标签下面的span标签的下面的input标签

#其他
p:nth-child(1)             # 选择第一个p标签,还可写为 p:first-child
p:nth-last-child(1)        # 选择倒数第一个p标签(要保证最后一个标签是p)
p:nth-of-type(n)					 # 选择器匹配属于父元素的特定类型的第 N 个子元素的每个元素.
p:only-child       		   # 唯一的p标签
P:nth-child(n+6):nth-child(-n+9)	# 选择某一个范围,选择第6个到第9个
p:nth-child(-n+6)				# 选择第1个到第6个
p:nth-child(2n)					# 选择列表中的偶数标签
P:nth-child(2n-1)				# 选择列表中的奇数标签

4. JS的使用,可以直接调用js方法来实现一些操作

from selenium import webdriver
browser = webdriver.Chrome()
browser.get("http://www.zhihu.com/explore")
js = 'document.querySelector("#history_list > li.history-record.lastdayitem > div.r-info.clearfix > div.cover-contain > a")'
browser.execute_script("$(arguments[0]).click()",js)

5. 检查元素是否存在

yes=driver.find_element_by_name(“login”).is_displayed()
#判断元素是否是存在的,返回true,说明是存在的,false表示不存在
print yes
# 返回false的原因有很多可能,可能是定位不准确换个方式,或者这个于是元素需要hover或者悬停才会显示出来,或者是display隐藏属性为none

6.没有定位元素直接回车操作

from selenium.webdriver.common.action_chains import ActionChains

driver = webdriver.Firefox()

ActionChains(driver).send_keys(Keys.ENTER).perform()

7.操作alert元素

本知识点转载:http://www.cnblogs.com/mengyu/p/6952774.html与对话框
当我们登录某些界面的时候,输入用户名和密码错误,会弹出一个alert(警告)对话框,如果不叉掉它是没法继续执行下去,所以无法通过定位的方式定位它的位置。

我们的弹出对话框主要分为三种类型:“警告消息框”,“确认消息框”,“提示消息对话”三种类型的对话框。

1.警告消息框(alert)

警告消息框提供了一个“确定”按钮让用户关闭该消息框,而且该消息框是模式对话框,也就是说用户必须先关闭该消息框然后才能继续进行操作。

2.确认消息框(confirm)

确认消息框向用户提示一个“是与否”问题,用户可以根据选择“确定”按钮和“取消”按钮。

3.提示消息对话(prompt)

提示消息框提供一个文本字段,用户可以在此字段输入一个答案来响应您的提示。有一个“确定”按钮和“取消”按钮。选择“确认”会响应对应的提示信息,选择“取消”会关闭对话框。

selenium提供switch_to_alert()方法定位到alert/confirm/prompt对话框。使用text/accept/dismiss/send_keys进行操作,这里注意的是send——keys只能对prompt操作,因为只有它是要输入内容的。

switch_to_alert() #定位弹出对话
text()                  #获取对话框文本值
accept()              #相当于点击“确认”
dismiss()              #相当于点击“取消”
send_keys()        #输入值,这个alter和confirm没有输入对话框,所以这里不能用,只能用于prompt

代码如下:

from selenium import webdriver
from time import sleep

driver = webdriver.Firefox()
driver.maximize_window()
driver.get('http://sahitest.com/demo/alertTest.htm')

driver.find_element_by_name('b1').click()

a1 = driver.switch_to.alert  # 通过switch_to.alert切换到alert
sleep(1)
print a1.text  # text属性输出alert的文本
a1.accept()  # alert“确认”
a1.dismiss()  # alert“取消”
sleep(1)

driver.quit()

3.处理prompt对话框

    #-*-coding:utf-8 -*-
    import time
    from selenium import webdriver
    driver = webdriver.Chrome()
    driver.maximize_window()
    '''获取对话框输入2,并且点击【确认】,文本框内提示<左哥是真笨啊>,点击【取消】文本框内提示<您没有按要求输入,请重新输入>'''
    driver.get('file:///C:/Users/hunk/Desktop/alter.html')
    '''获取prompt对话框的按钮,点击按钮,弹出confirm对话框'''
    driver.find_element_by_xpath('/html/body/div/input[1]').click()
    '''获取prompt对话框'''
    dialog_box = driver.switch_to_alert()
    '''添加等待时间'''
    time.sleep(2)
    '''获取对话框的内容'''
    print (dialog_box.text)  #打印警告对话框内容
    dialog_box.send_keys("2")  #弹出框内输入2
    dialog_box.accept()  #接受
    print (driver.find_element_by_xpath('//*[@id="textSpan"]/font').text)  #获取关闭弹窗结果  #获取确认弹窗结果
    '''这里等待几秒在测试取消'''
    time.sleep(2)
    #************************点击【取消】,并且获取显示结果**********************
    driver.find_element_by_xpath('/html/body/div/input[1]').click()
    '''获取prompt对话框'''
    dialog_box = driver.switch_to_alert()
    '''添加等待时间'''
    time.sleep(2)
    dialog_box.dismiss()  #关闭对话框
    print (driver.find_element_by_xpath('//*[@id="textSpan"]/font').text)  #获取关闭弹窗结果
    time.sleep(2)
    driver.quit()

8.iframe操作

iframe属于内嵌网页,直接定位定位不到iframe内的元素,需要切换到指定的iframe标签内。
对iframe进行操作,需要用到一下种方法:

switch_to_iframe()                       切换到iframe上
switch_to.frame()                         切换到iframe上
switch_to.default_content()         切换回原主页面

def iframe_1(self):
	# iframe 标签
	iframe = self.fd.get_ element(' iframe')
	self.driver.switch_ to.frame (iframe)
	
def switch_to(self):
	# 返回上一层
	self.driver.switch_to.default _content()
	time.sleep(0.3)

def send_commodity.name(self, commodity_ name) :
	#输入密码
	self.loger.info("输入名称")
	# self.switch_ to()
	# self.iframe_ 1()
	time . sleep(2)
	# get_element是封装好的方法这里直接调用
	commodity = self . fd.get_element(' commodity_ name ').send_ keys (name)
	
iframe_1()		# 进入iframe标签
send_commodity()	# 操作
switch_to()		# 退出iframe

9.多窗口切换

# 获取打开的多个窗口句柄
windows = driver.window_handles
# 切换到当前最新打开的窗口
driver.switch_to.window(windows[-1])

10.link_text定位与partial_link_text定位

# 这里使用hao123网站界面
################### link_text
from selenium import webdriver
from time import sleep
 
#这里使用hao123网站界面
 
#获取浏览器对象
driver=webdriver.Firefox()
#获取网络链接
url="https://www.hao123.com/"
driver.get(url)
#获取hao123网站的12306超链接位置,并点击超链接
driver.find_element_by_link_text("12306").click()
 
#暂停6秒
sleep(6)
#退出浏览器驱动
driver.quit()

################  partial_link_text定位
# 获取浏览器对象
driver = webdriver.Firefox()
# 获取网络链接
url = "https://www.hao123.com/"
driver.get(url)
# 获取hao123网站的12306超链接位置,并点击超链接
# driver.find_element_by_link_text("12306").click()
driver.find_element(By.PARTIAL_LINK_TEXT,"哔哩").click()
# 暂停6秒
sleep(6)
# 退出浏览器驱动
driver.quit()

11.键盘操作

# -*- coding: utf-8 -*-
from selenium import webdriver
# 导入selenium中的键盘事件keys
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
# 搜索框中输入‘selenium’
driver.find_element_by_id('kw').send_keys('selenium')
# 调用键盘事件	空格
driver.find_element_by_id('kw').send_keys(Keys.SPACE) 
driver.find_element_by_id('kw').send_keys('python')
# 调用键盘事件	组合键control+a
driver.find_element_by_id('kw').send_keys(Keys.CONTROL, 'a')
# 调用键盘事件	组合键control+c
driver.find_element_by_id('kw').send_keys(Keys.CONTROL, 'c')
# 调用键盘事件	组合键control+v
driver.find_element_by_id('kw').send_keys(Keys.CONTROL, 'v')
# 调用键盘事件	组合键回车键
driver.find_element_by_id('kw').send_keys(Keys.ENTER)
time.sleep(3)
driver.close()
# 和输入内容一样,注意点,这个输入不是输入字符串
send_keys()
send_keys(Keys.BACK_SPACE)  删除键Backspace
send_keys(Keys.SPACE)  空格键
send_keys(Keys.TAB)  Tab
send_keys(Keys.ESCAPE)  Esc
send_keys(Keys.ENTER)  Enter
send_keys(Keys.CONTROL, 'a')  Ctrl+a
send_keys(Keys.CONTROL, 'c')  Ctrl+c
send_keys(Keys.CONTROL, 'x')  Ctrl+x
send_keys(Keys.CONTROL, 'v')  Ctrl+v
send_keys(Keys.F1)  F1

Keys.BACK_SPACE:回退键(BackSpace)
Keys.TAB:制表键(Tab)
Keys.ENTER:回车键(Enter)
Keys.SHIFT:大小写转换键(Shift)
Keys.CONTROL:Control键(Ctrl)
Keys.ALT:ALT键(Alt)
Keys.ESCAPE:返回键(Esc)
Keys.SPACE:空格键(Space)
Keys.PAGE_UP:翻页键上(Page Up)
Keys.PAGE_DOWN:翻页键下(Page Down)
Keys.END:行尾键(End)
Keys.HOME:行首键(Home)
Keys.LEFT:方向键左(Left)
Keys.UP:方向键上(Up)
Keys.RIGHT:方向键右(Right)
Keys.DOWN:方向键下(Down)
Keys.INSERT:插入键(Insert)
DELETE:删除键(Delete)
NUMPAD0 ~ NUMPAD9:数字键1-9
F1 ~ F12:F1 - F12键
(Keys.CONTROL, ‘a’):组合键Control+a,全选
(Keys.CONTROL, ‘c’):组合键Control+c,复制
(Keys.CONTROL, ‘x’):组合键Control+x,剪切
(Keys.CONTROL, ‘v’):组合键Control+v,粘贴

12.鼠标操作

# 实例
from selenium import webdriver
from time import sleep
from selenium.webdriver import ActionChains
driver = webdriver.Chrome(r"chromedriver.exe")
driver.implicitly_wait(5)
driver.get(url="https://www.runoob.com/try/try.php?filename=tryjs_events_mouseover")
driver.maximize_window()
#切换iframe
driver.switch_to.frame(driver.find_element_by_xpath('//iframe[@id="iframeResult"]'))
#元素定位
element= driver.find_element_by_xpath('//div[@οnmοuseοver="mOver(this)"]')
# 首先把浏览器对象放在Act ionChains中, 然后使用鼠标事件操作,最后提交操作
# 移动鼠标到元素上触发事件
ActionChains(driver).move_to_element(element).perform()
# 
sleep(5)
driver.quit()
  • perform(self)-执行鼠标操作方法
  • reset_actions()清楚操作子令
  • click(on_element=None)-点击鼠标左键
  • click_and_hold(on_element=None): 鼠标左键,不松开
  • context_click(on_element=None): 鼠标右键
  • double_click(on_element=None): 双击鼠标左键
  • drag_and_drop(source, target):拖拽到某个元素然后松开
  • drag_and_drop_by_ofset(source, xoffset, yoffset) :拖拽到某个坐标然后松开
  • key_down(value, element=None):按下某个键盘上的
  • key_up(value, element=None) :松开某个
  • move_by_ofsfet(xoffset, yoffset):鼠标从当前位置移动到某个坐标
  • move_to_element(to_element) :鼠标移动到某个元素
  • move_to_element _with_offset(to_element, xoffset, yoffset):移动到
    距某个元素(左上角坐标)多少距离的位置
  • pause(seconds):暂停操作(秒)
  • release(on_element=None): 在元素上释放按住的鼠标按钮
  • send_keys(keys_to_send): 发送某个键到当前焦点的元素
  • send_keys_to_element(element, *keys_to_send) :发送某个键到指定元素

13.JS高级操作

selenium点击输入需要与键盘鼠标配合外,还可以与JS配合,可以删除js内元素,或者添加JS元素
通过选择器,获取一个元素:document.querySelector(“css selector”)
通过CSS选择器,获取元素列表:document.querySelectorAll(“css selector”)

# send_keys输入元素js写法
js='document.querySelector("#UserID").value="%s"'%username
driver.execute_script(js)
js='document.querySelector("#Paswd").value=%s'%pwd
driver.execute_script(js)
# 进行点击操作
js2 = 'document.querySelector("#btnLogin").click()'
driver.execute_script(js2)
js = "document.querySelector('a[title='导出']').click()"
driver.execute_script(js)

# 通过JS增加属性值:setAttribute方法可增加或修改属性,属性存在时修改,不存在时增加
js1 = "document.querySelector('#select_status').setAttribute('class','move')"
driver.execute_script(js1)
 
# 删除属性
js2 = 'document.querySelector("kw").removeAttribute("maxlength")'
driver.execute_script(js2)
 
# 如果想要获取js返回的属性值,需要js前加return
js3 = 'return  document.querySelector("kw").getAttribute("name")'
attr = driver.execute_script(js3)
print(attr)
 
# 通过JS修改id属性值
js4 = 'document.querySelector("kw").setAttribute("id","mouse")'
driver.execute_script(js4)

# 时间输入
# 定位时间元素
driver.execute_script("dat=document.querySelector('train_date'); dat.removeAttribute('readonly')")
js = "document.querySelector('train_date').removeAttribute('readonly')"
driver.execute_script(js)
# 修改元素值
driver.execute_script("document.querySelector('train_date').value='2020-10-01'")

#右侧滚动条:
    #⑴滑动页面到底部:document.documentElement.scrollTop=10000
    #⑵滑动页面到顶部:document.documentElement.scrollTop=0
    #⑶scrollTop:指滚动条距离顶部的距离
        #①设置很大表示:最底部
       # ②设置为0表示:顶部

#横向滚动条:window.scrollTo(xpos,ypos)
    #⑴xpos:必需,要在窗口文档显示区左上角显示的文档的x坐标(横向距离)
    #⑵ypos:必需,要在窗口文档显示区左上角显示的文档的y坐标(纵向距离)
# 操作滚动条:滑动到浏览器底部
driver.execute_script('document.documentElement.scrollTop=10000')
# 操作滚动条:滑动到浏览器顶部
driver.execute_script('document.documentElement.scrollTop=0')
time.sleep(2)
# 操作滚动条:滑动到指定位置
driver.execute_script('window.scrollTo(1600,0)')
滚动暂时没有调试好

14.点击文件上传,传输本地文件路径

import pywinauto
from pywinauto.keyboard import send_keys


def video_upload(self):
    self.app = pywinauto.Desktop()
    # 选择文件上传的窗口
    dlg = self.app["打开"]
    time.sleep(2)
    # 选择文件地址输入框,点击激活
    dlg["Toolbar3"].click()
    # 键盘输入上传文件的路径  1
    send_keys("文件夹路径")
    # 键盘输入回车,打开该路径
    send_keys("{VK_RETURN}")
    # 选中文件名输入框,输入文件名  2
    dlg["文件名(&N):Edti"].type_keys("文件名")
    # 点击打开
    dlg["打开(&O)"].click()
    time.sleep(10)

15.显示等待封装Wait

# 用于实现智能等待页面元素的出现
# encoding = utf-8
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver
driver = webdriver.Chrome(executable_path=r"F:\automation\webdriver\chromedriver.exe")
driver.get("http://mail.126.com")

def wait_t(element, wait_time=6):
	 # 判断元素是否存在,存在执行下下面代码,不存在报错
    WebDriverWait(driver, wait_time, 0.2).until(EC.visibility_of(element))
    print(element.text,'执行')
def send_key(values, value):
    how, what = values.split('=', 1)[0], values.split('=', 1)[1]
    print(how, what)
    element = driver.find_element(set_by(how), what)
    print("---等待前")
    # WebDriverWait(driver, 6, 0.2).until(EC.visibility_of(element))
    wait_t(element)
    print("----等待后")
    element.send_keys(value)
    print("执行后")
email = "css=#id_email"
# wait_alert(values)
data = 525
send_key(email, data)
# -----------------下面是详细到某一点的定位
# 实例化WaitUtil类
waitUtil = WaitUtil(driver)
# 判断如果id = x-URS-iframe的iframe存在则切换进去
wf = waitUtil.frame_to_be_available_and_switch_to_it("id", "x-URS-iframe")
# 等待页面元素xpath = //input[@name='email']的出现
wv = waitUtil.visibility_element_located("xpath", "//input[@name='email']")
# 显示等待页面元素出现在DOM中,但并不一定可见,存在则返回该页面元素对象
wp = waitUtil.presence_of_element_located("xpath", "//input[@name='email']")
driver.quit()
"""
WebDriverWait(driver,10).until(EC.title_is(u"百度一下,你就知道"))
'''判断title,返回布尔值'''

WebDriverWait(driver,10).until(EC.title_contains(u"百度一下"))
'''判断title,返回布尔值'''

WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'kw')))
'''判断某个元素是否被加到了dom树里,并不代表该元素一定可见,如果定位到就返回WebElement'''

WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID,'su')))
'''判断某个元素是否被添加到了dom里并且可见,可见代表元素可显示且宽和高都大于0'''

WebDriverWait(driver,10).until(EC.visibility_of(driver.find_element(by=By.ID,value='kw')))
'''判断元素是否可见,如果可见就返回这个元素'''

WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'.mnav')))
'''判断是否至少有1个元素存在于dom树中,如果定位到就返回列表'''

WebDriverWait(driver,10).until(EC.visibility_of_any_elements_located((By.CSS_SELECTOR,'.mnav')))
'''判断是否至少有一个元素在页面中可见,如果定位到就返回列表'''

WebDriverWait(driver,10).until(EC.text_to_be_present_in_element((By.XPATH,"//*[@id='u1']/a[8]"),u'设置'))
'''判断指定的元素中是否包含了预期的字符串,返回布尔值'''

WebDriverWait(driver,10).until(EC.text_to_be_present_in_element_value((By.CSS_SELECTOR,'#su'),u'百度一下'))
'''判断指定元素的属性值中是否包含了预期的字符串,返回布尔值'''

#WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it(locator))
'''判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False'''
#注意这里并没有一个frame可以切换进去
    
WebDriverWait(driver,10).until(EC.invisibility_of_element_located((By.CSS_SELECTOR,'#swfEveryCookieWrap')))
'''判断某个元素在是否存在于dom或不可见,如果可见返回False,不可见返回这个元素'''
#注意#swfEveryCookieWrap在此页面中是一个隐藏的元素

WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//*[@id='u1']/a[8]"))).click()
'''判断某个元素中是否可见并且是enable的,代表可点击'''
driver.find_element_by_xpath("//*[@id='wrapper']/div[6]/a[1]").click()
#WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//*[@id='wrapper']/div[6]/a[1]"))).click()

#WebDriverWait(driver,10).until(EC.staleness_of(driver.find_element(By.ID,'su')))
'''等待某个元素从dom树中移除'''
#这里没有找到合适的例子

WebDriverWait(driver,10).until(EC.element_to_be_selected(driver.find_element(By.XPATH,"//*[@id='nr']/option[1]")))
'''判断某个元素是否被选中了,一般用在下拉列表'''

WebDriverWait(driver,10).until(EC.element_selection_state_to_be(driver.find_element(By.XPATH,"//*[@id='nr']/option[1]"),True))
'''判断某个元素的选中状态是否符合预期'''

WebDriverWait(driver,10).until(EC.element_located_selection_state_to_be((By.XPATH,"//*[@id='nr']/option[1]"),True))
'''判断某个元素的选中状态是否符合预期'''
driver.find_element_by_xpath(".//*[@id='gxszButton']/a[1]").click()

instance = WebDriverWait(driver,10).until(EC.alert_is_present())
'''判断页面上是否存在alert,如果有就切换到alert并返回alert的内容'''
print instance.text
instance.accept()
···

  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yuno Wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值