python 自定义模块加密_Python开发【第一篇】Python基础之自定义模块和内置模块...

为什么要有模块,将代码归类。模块,用一砣代码实现了某个功能的代码集合。

Python中叫模块,其他语言叫类库。

类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合。而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不同的.py文件中),n个 .py 文件组成的代码集合就称为模块。

如:os 是系统相关的模块;file是文件操作相关的模块

模块分为三种:

自定义模块

第三方模块

内置模块

自定义模块

1、定义模块

2、导入模块

模块秉承先导入后使用得原则。

Python之所以应用越来越广泛,在一定程度上也依赖于其为程序员提供了大量的模块以供使用,如果想要使用模块,则需要导入。导入模块有一下几种方法:

单模块导入:

import module

from s4import * (导入s4模块中的的所有函数)

嵌套在文件夹下:

1、安装模块:

安装pip模块:

Python3 的pip3 默认已安装

Python2.7 的pip 需要单独安装

两种requests安装方式:

#pip3 install requests

#源码:https://github.com/kennethreitz/requests/tarball/master

cd F:\kennethreitz-requests-v2.11.1-76-g50486cf\kennethreitz-requests-50486cf

python3 setup.py install

View Code

报错:

出现这种报错,需要升级下pip版本:

c:\>pip3 install requests

Fatal errorin launcher: Unable to create process using '"'解决:

python-m pip install -U pip

View Code

pycharm升级pip:

2、使用模块

获取天气预报:

importrequests

response= requests.get('http://wthrcdn.etouch.cn/weather_mini?city=北京')

response.encoding= 'utf-8'

print(response.text)

View Code

基于天气API获取天气相关JSON数:

importrequestsimportjson

response= requests.get('http://wthrcdn.etouch.cn/weather_mini?city=深圳')

response.encoding= 'utf-8'

#print(response.text)

dic =json.loads(response.text)print(dic)

View Code

#1、无参数实例

importrequests

ret= requests.get('https://github.com/timeline.json')print(ret.url)print(ret.text)#2、有参数实例

importrequests

payload= {'key1': 'value1', 'key2': 'value2'}

ret= requests.get("http://httpbin.org/get", params=payload)print(ret.url)print(ret.text)

GET请求

GET请求

#1、基本POST实例

importrequests

payload= {'key1': 'value1', 'key2': 'value2'}

ret= requests.post("http://httpbin.org/post", data=payload)print(ret.text)#2、发送请求头和数据实例

importrequestsimportjson

url= 'https://api.github.com/some/endpoint'payload= {'some': 'data'}

headers= {'content-type': 'application/json'}

ret= requests.post(url, data=json.dumps(payload), headers=headers)print(ret.text)print(ret.cookies)

POST请求

POST请求

requests.get(url, params=None, **kwargs)

requests.post(url, data=None, json=None, **kwargs)

requests.put(url, data=None, **kwargs)

requests.head(url,**kwargs)

requests.delete(url,**kwargs)

requests.patch(url, data=None, **kwargs)

requests.options(url,**kwargs)#以上方法均是在此方法的基础上构建

requests.request(method, url, **kwargs)

其他请求

其他请求

更多requests模块相关的文档见:http://cn.python-requests.org/zh_CN/latest/

3、Http请求和XML实例

实例:检测QQ账号是否在线

importurllibimportrequestsfrom xml.etree importElementTree as ET#使用内置模块urllib发送HTTP请求,或者XML格式内容

"""f = urllib.request.urlopen('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508')

result = f.read().decode('utf-8')"""

#使用第三方模块requests发送HTTP请求,或者XML格式内容

r = requests.get('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508')

result=r.text#解析XML格式内容

node =ET.XML(result)#获取内容

if node.text == "Y":print("在线")else:print("离线")

View Code

实例:查看火车停靠信息

importurllibimportrequestsfrom xml.etree importElementTree as ET#使用内置模块urllib发送HTTP请求,或者XML格式内容

"""f = urllib.request.urlopen('http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=G666&UserID=')

result = f.read().decode('utf-8')"""

#使用第三方模块requests发送HTTP请求,或者XML格式内容

r = requests.get('http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=G666&UserID=')

result=r.text#解析XML格式内容

root =ET.XML(result)for node in root.iter('TrainDetailInfo'):print(node.find('TrainStation').text,node.find('StartTime').text,node.tag,node.attrib)

View Code

注:更多接口猛击这里

二、序列化

Python中用于序列化的两个模块

json     用于【字符串】和 【python基本数据类型】 间进行转换,更加适合跨语言

pickle   用于【python特有的类型】 和 【python基本数据类型】间进行转换,仅适用于Python

举例:如果Python去写游戏存档得话、只能用pickle。

Json模块提供了四个功能:dumps、dump、loads、load

pickle模块提供了四个功能:dumps、dump、loads、load

#将python基本数据类型转化成为字符串形式

import json

dic = {'k1':'v1'}

print(dic,type(dic))

result = json.dumps(dic)

print(result,type(result))

# 将Python字符串形式转化成基本数据类型

s1 = '{"k1":123}'

dic = json.loads(s1)

print(dic,type(dic))

#py基本数据类型转换字符串

import json

r = json.dumps([11,22,33])

# li = '["alex","eric"]'

li = "['alex','eric']"

ret = json.loads(li) #反序列化时,一定要使用“双引号

print(ret,type(ret))

在Python中,单引号和双引号都表示字符串。其他语言里,单引号引起来叫字符,双引号引起来叫字符串。

如果想跨语言之间,共同都能用,需要使用“ 双引号。

json.dumps()和json.loads()

json.dump()和json.load()

dump会比dumps多做一步操作,先转成字符串,再写到文件里。

load会比loads多做一步操作,先从文件取出,再转化成列表。

li = [11,22,33]

json.dump(li,open('db','w')

li = json.load(open('db','r'))

print(type(li),li)

import pickle

li = [11,22,33]

r = pickle.dumps(li)

print(r)

result = pickle.loads(r)

print(result)

三、time & datetime模块

import time

print(time.asctime()) #返回时间格式"Fri Aug 19 11:14:16 2016",

print(time.ctime()) #返回Fri Aug 19 12:38:29 2016 格式

print(time.asctime(time.localtime())) #返回时间格式"Fri Aug 19 11:14:16 2016",同上

print(time.localtime()) #返回本地时间 的struct time对象格式

print(time.gmtime(time.time()-800000)) #返回utc时间的struc时间对象格式

print(time.altzone) #返回与utc时间的时间差,以秒计算

print(time.clock()) #返回处理器时间,3.3开始已废弃 , 改成了time.process_time()测量处理器运算时间,不包括sleep时间,不稳定,mac上测不出来

#日期字符串 转成 时间戳

string_2_struct = time.strptime("2016/05/22","%Y/%m/%d") #将 日期字符串 转成 struct时间对象格式

print(string_2_struct)

struct_2_stamp = time.mktime(string_2_struct) #将struct时间对象转成时间戳

print(struct_2_stamp)

#将时间戳转为字符串格式

print(time.gmtime(time.time()-86640)) #将utc时间戳转换成struct_time格式

print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #将utc struct_time格式转成指定的字符串格式

#时间加减

import datetime

print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925

print(datetime.date.fromtimestamp(time.time()) ) # 时间戳直接转成日期格式 2016-08-19

print(datetime.datetime.now() )

print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天

print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天

print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时

print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分

#时间替换

c_time = datetime.datetime.now()

print(c_time.replace(minute=3,hour=2))

时间比较:

current_time = datetime.datetime.now()

time_obj=current_time.replace(2015,5)

print(current_time>time_obj)

%Y Year with century as a decimal number.

%m Month as a decimal number [01,12].

%d Day of the month as a decimal number [01,31].

%H Hour (24-hour clock) as a decimal number [00,23].

%M Minute as a decimal number [00,59].

%S Second as a decimal number [00,61].

%z Time zone offset from UTC.

%a Locale's abbreviated weekday name.

%A Locale's full weekday name.

%b Locale's abbreviated month name.

%B Locale's full month name.

%c Locale's appropriate date and time representation.

%I Hour (12-hour clock) as a decimal number [01,12].

%p Locale's equivalent of either AM or PM.

格式化占位符

四、logging模块

很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug(), info(), warning(), error() and critical() 5个级别,下面我们看一下怎么用。

最简单用法

import logging

logging.warning("user [alex] attempted wrong password more than 3 times")

logging.critical("server is down")

#输出

WARNING:root:user [alex] attempted wrong password more than 3 times

CRITICAL:root:server is down

看一下这几个日志级别分别代表什么意思

Level

When it’s used

DEBUG

Detailed information, typically of interest only when diagnosing problems.

详细信息,通常用于诊断问题

INFO

Confirmation that things are working as expected.

确定事情按照预期得工作

WARNING

An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.

表明一些意想不到的事情发生了,或说明一些问题在不久的将来(例如低磁盘空间)。软件仍然是按预期工作。

ERROR

Due to a more serious problem, the software has not been able to perform some function.

由于一个更严重的问题,软件没能执行一些功能。

CRITICAL

A serious error, indicating that the program itself may be unable to continue running.

一个严重的错误,这表明程序本身可能无法继续运行。

如果想把日志写到文件里,也很简单

import logging

logging.basicConfig(filename='example.log',level=logging.INFO)

logging.debug('This message should go to the log file')

logging.info('So should this')

logging.warning('And this, too')

其中下面这句中的level=loggin.INFO意思是,把日志纪录级别设置为INFO,也就是说,只有比日志是INFO或比INFO级别更高的日志才会被纪录到文件里,在这个例子, 第一条日志是不会被纪录的,如果希望纪录debug的日志,那把日志级别改成DEBUG就行了。

logging.basicConfig(filename='example.log',level=logging.INFO)

感觉上面的日志格式忘记加上时间啦,日志不知道时间怎么行呢,下面就来加上!

import logging

logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')

logging.warning('is when this event was logged.')

#输出

12/12/2010 11:46:36 AM is when this event was logged.

如果想同时把log打印在屏幕和文件日志里,就需要了解一点复杂的知识了

The logging library takes a modular approach and offers several categories of components: loggers, handlers, filters, and formatters.

#日志库采用模块化的方法,提供了几种类型的组件:logger/handlers/filters/formatters

Loggers expose the interface that application code directly uses. #logger是应用程序直接调用得公开接口

Handlers send the log records (created by loggers) to the appropriate destination. #处理程序发送日志记录到相应的目的地

Filters provide a finer grained facility for determining which log records to output. #过滤器提供过滤哪些日志记录输出的功能

Formatters specify the layout of log records in the final output. #格式化输出日志记录

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import logging

#create logger

logger = logging.getLogger('TEST-LOG') #首先获取日志,TEST-LOG是标记

logger.setLevel(logging.INFO) #设置一个全局的日志级别INFO

#create console handler and set level to debug

ch = logging.StreamHandler() #打印输出到屏幕上

ch.setLevel(logging.DEBUG) #往屏幕输出的日志级别DEBUG

# create file handler and set level to warning

fh = logging.FileHandler("access.log",'a',encoding='utf-8') #输出到文件access.log

fh.setLevel(logging.WARNING) #输出到日志文件的级别WARNING

fh_err = logging.FileHandler("error.log",'a',encoding='utf-8') #输出错误日志到error.log文件

fh_err.setLevel(logging.ERROR) #输出到文件的级别是ERROR

# create formatter

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') #输出文件的格式

formatter_for_file = logging.Formatter('%(asctime)s - %(module)s -%(lineno)d - %(levelname)s - %(message)s')

# add formatter to ch and fh

ch.setFormatter(formatter)

fh.setFormatter(formatter_for_file)

fh_err.setFormatter(formatter)

# add ch and fh to logger

logger.addHandler(ch) #tell the logger to input the log into specified handler 把日志打印到指定得地方

logger.addHandler(fh)

logger.addHandler(fh_err)

# 'application' code

logger.debug('debug message')

logger.info('info message')

logger.warn('warn message')

logger.error('error message')

logger.critical('critical message')

日志等级:

CRITICAL = 50

FATAL = CRITICAL

ERROR = 40

WARNING = 30

WARN = WARNING

INFO = 20

DEBUG = 10

NOTSET = 0

注:只有【当前写等级】大于【日志等级】时,日志文件才被记录。

五、sys模块

用于提供对Python解释器相关的操作:

sys.path 是最重要的。

sys.argv 命令行参数List,第一个元素是程序本身路径

sys.exit(n) 退出程序,正常退出时exit(0)

sys.version 获取Python解释程序的版本信息

sys.maxint 最大的Int值

sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值

sys.platform 返回操作系统平台名称

sys.stdin 输入相关

sys.stdout 输出相关

sys.stderror 错误相关

实例:进度条百分比

importsysimporttimedefview_bar(num, total):

rate= num /total

rate_num= int(rate * 100)

r= '\r%s>%d%%' %("="*num, rate_num)

sys.stdout.write(r)

sys.stdout.flush()if __name__ == '__main__':for i in range(0, 101):

time.sleep(0.1)

view_bar(i,100)

View Code

六、os模块

用于提供系统级别的操作:

os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径

os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd

os.curdir 返回当前目录: ('.')

os.pardir 获取当前目录的父目录字符串名:('..')

os.makedirs('dir1/dir2') 可生成多层递归目录

os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推

os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname

os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname

os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印

os.remove() 删除一个文件

os.rename("oldname","new") 重命名文件/目录

os.stat('path/filename') 获取文件/目录信息

os.sep 操作系统特定的路径分隔符,win下为"\\",Linux下为"/"

os.linesep 当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"

os.pathsep 用于分割文件路径的字符串

os.name 字符串指示当前使用平台。win->'nt'; Linux->'posix'

os.system("bash command") 运行shell命令,直接显示

os.environ 获取系统环境变量

os.path.abspath(path) 返回path规范化的绝对路径

os.path.split(path) 将path分割成目录和文件名二元组返回

os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素

os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素

os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False

os.path.isabs(path) 如果path是绝对路径,返回True

os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False

os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False

os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略

os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间

os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间

最重要的三个,必会:

七、hashlib

用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

import hashlib

# ######## md5 ########

hash = hashlib.md5()

# help(hash.update)

hash.update(bytes('admin', encoding='utf-8'))

print(hash.hexdigest())

print(hash.digest())

######## sha1 ########

hash = hashlib.sha1()

hash.update(bytes('admin', encoding='utf-8'))

print(hash.hexdigest())

# ######## sha256 ########

hash = hashlib.sha256()

hash.update(bytes('admin', encoding='utf-8'))

print(hash.hexdigest())

# ######## sha384 ########

hash = hashlib.sha384()

hash.update(bytes('admin', encoding='utf-8'))

print(hash.hexdigest())

# ######## sha512 ########

hash = hashlib.sha512()

hash.update(bytes('admin', encoding='utf-8'))

print(hash.hexdigest())

以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。

import hashlib

# ######## md5 ########

hash = hashlib.md5(bytes('898oaFs09f',encoding="utf-8"))

hash.update(bytes('admin',encoding="utf-8"))

print(hash.hexdigest())

python内置还有一个 hmac 模块,它内部对我们创建 key 和 内容 进行进一步的处理然后再加密

import hmac

h = hmac.new(bytes('898oaFs09f',encoding="utf-8"))

h.update(bytes('admin',encoding="utf-8"))

print(h.hexdigest())

八、re

python中re模块提供了正则表达式相关操作

字符:

. 匹配除换行符以外的任意字符

\w匹配字母或数字或下划线或汉字

\s匹配任意的空白符

\d匹配数字

\b匹配单词的开始或结束

^匹配字符串的开始

$匹配字符串的结束

次数:

* 重复零次或更多次

+重复一次或更多次

?重复零次或一次

{n}重复n次

{n,}重复n次或更多次

{n,m}重复n到m次

match

# match,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None

match(pattern, string, flags=0)

# pattern: 正则模型

# string : 要匹配的字符串

# falgs : 匹配模式

X VERBOSE Ignore whitespace and comments for nicer looking RE's.

I IGNORECASE Perform case-insensitive matching.

M MULTILINE "^" matches the beginning of lines (after a newline)

as well as the string.

"$" matches the end of lines (before a newline) as well

as the end of the string.

S DOTALL "." matches any character at all, including the newline.

A ASCII For string patterns, make \w, \W, \b, \B, \d, \D

match the corresponding ASCII character categories

(rather than the whole Unicode categories, which is the

default).

For bytes patterns, this flag is the only available

behaviour and needn't be specified.

L LOCALE Make \w, \W, \b, \B, dependent on the current locale.

U UNICODE For compatibility only. Ignored for string patterns (it

is the default), and forbidden for bytes patterns.

# 无分组

r= re.match("h\w+", origin)

print(r.group()) # 获取匹配到的所有结果

print(r.groups()) # 获取模型中匹配到的分组结果

print(r.groupdict()) # 获取模型中匹配到的分组结果

# 有分组

# 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)

r= re.match("h(\w+).*(?P\d)$", origin)

print(r.group()) # 获取匹配到的所有结果

print(r.groups()) # 获取模型中匹配到的分组结果

print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组

Demo

View Code

search

# search,浏览整个字符串去匹配第一个,未匹配成功返回None

# search(pattern, string, flags=0)

# 无分组

r= re.search("a\w+", origin)

print(r.group()) # 获取匹配到的所有结果

print(r.groups()) # 获取模型中匹配到的分组结果

print(r.groupdict()) # 获取模型中匹配到的分组结果

# 有分组

r= re.search("a(\w+).*(?P\d)$", origin)

print(r.group()) # 获取匹配到的所有结果

print(r.groups()) # 获取模型中匹配到的分组结果

print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组

demo

View Code

findall

# findall,获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元祖;

# 空的匹配也会包含在结果中

#findall(pattern, string, flags=0)

# 无分组

r= re.findall("a\w+",origin)

print(r)

# 有分组

origin= "hello alex bcd abcd lge acd 19"r= re.findall("a((\w*)c)(d)", origin)

print(r)

Demo

View Code

sub

# sub,替换匹配成功的指定位置字符串

sub(pattern, repl, string, count=0, flags=0)

# pattern: 正则模型

# repl : 要替换的字符串或可执行对象

# string : 要匹配的字符串

# count : 指定匹配个数

# flags : 匹配模式

# 与分组无关

origin= "hello alex bcd alex lge alex acd 19"r= re.sub("a\w+", "999", origin, 2)

print(r)

View Code

split

# split,根据正则匹配分割字符串

split(pattern, string, maxsplit=0, flags=0)

# pattern: 正则模型

# string : 要匹配的字符串

# maxsplit:指定分割个数

# flags : 匹配模式

# 无分组

origin= "hello alex bcd alex lge alex acd 19"r= re.split("alex", origin, 1)

print(r)

# 有分组

origin= "hello alex bcd alex lge alex acd 19"r1= re.split("(alex)", origin, 1)

print(r1)

r2= re.split("(al(ex))", origin, 1)

print(r2)

Demo

View Code

IP:^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$

手机号:^1[3|4|5|8][0-9]\d{8}$

邮箱:

[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+常用正则表达式

View Code

import re

origin = "hello alex bcd alex lge alex acd 19"

r = re.split("a(le)x",origin,1)

print(r)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的公寓报修管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本公寓报修管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此公寓报修管理系统利用当下成熟完善的Spring Boot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。公寓报修管理系统有管理员,住户,维修人员。管理员可以管理住户信息和维修人员信息,可以审核维修人员的请假信息,住户可以申请维修,可以对维修结果评价,维修人员负责住户提交的维修信息,也可以请假。公寓报修管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:公寓报修管理系统;Spring Boot框架;MySQL;自动化;VUE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值