文章目录
1、json&pickle模块
1.1、什么是序列化与反序列化
序列化:
内存中某一类的数据 ————> 特殊的格式
反序列化:
内存中某一类的数据 <———— 特殊的格式
1.2、为何要用序列化
1、存档: 把内存中的数据持久化到硬盘
2、跨平台交互数据
在python中:
存档 => 推荐使用pickle格式
跨平台交互 => 推荐使用json格式
1.3、如何序列化
1.3.1、比较low的序列化与反序列化方式
items = ["圣剑", "蝴蝶", "BKB"]
list_str = str(items)
# 序列化
with open('db.txt'. mode='wt', encoding='utf-8') as f:
f.write(list_str)
# 反序列化
with open('db.txt'. mode='rt', encoding='utf-8') as f:
data = f.read()
items = eval(data)
1.3.2、json的序列化与反序列化方式
优点: 跨平台交互数据
缺点: 无法识别所有的python数据类型
# 方式一:
import json
dict = {'k1': 111, 'k2': 222, 'k3': 333}
# 序列化
res = json.dumps(dict)
print(res, type(res)) # {"k1": 111, "k2": 222, "k3": 333} <class 'str'>
# 反序列化
res1 = json.loads(res)
print(res1, type(res1)) # {'k1': 111, 'k2': 222, 'k3': 333} <class 'dict'>
# 方式二:
import json
dict = {'k1': 111, 'k2': 222, 'k3': 333}
# 序列化
with open('a.json', mode='wt', encoding='utf-8') as fp:
json.dump(dict, fp)
# 反序列化
with open('a.json', mode='rt', encoding='utf-8') as fp:
data = json.load(fp)
print(data, type(data)) # {'k1': 111, 'k2': 222, 'k3': 333} <class 'dict'>
1.3.3、pickle的序列化与反序列化方式
优点: 可以识别所有python数据类型
缺点: 只能用于python中,无法跨平台交互
# 方式一:
import pickle
s = {'a', 'b', 'c'}
# 序列化
res = pickle.dumps(s)
print(res, type(res)) # b'\x80\x04\x95\x11\x00\x00\x00\x00\x00\x00\x00\x8f\x94(\x8c\x01b\x94\x8c\x01a\x94\x8c\x01c\x94\x90.' <class 'bytes'>
# 反序列化
res1 = pickle.loads(res)
print(res1, type(res1)) # {'b', 'a', 'c'} <class 'set'>
# 方式二:
import pickle
s = {'a', 'b', 'c'}
# 序列化
with open('b.json', mode='wb') as f:
pickle.dump(s, f)
# 反序列化
with open('b.json', mode='rb') as f:
res = pickle.load(f)
print(res, type(res)) # {'a', 'c', 'b'} <class 'set'>
1.4、猴子补丁
1.4.1、定义
在运行时对方法、类、属性、功能进行修改,把新的代码作为解决方案代替原有的程序,也就是为其打上补丁
1.4.2、使用
很多代码用到 import json,后来发现ujson性能更高,如果觉得把每个文件的import json 改成 import ujson as json成本较高,或者说想测试一下用ujson替换json是否符合预期,只需要在入口加上如下代码:
import json
import ujson
def monkey_patch_json():
json.__name__ = 'ujson'
json.dumps = ujson.dumps
json.loads = ujson.loads
monkey_patch_json()
2、hashlib模块
2.1、hash定义与特点
hash是一种算法(md5、sha256、sha512等),我们为该算法传入文本内容,该算法会计算得到一串hash值
hash值具备以下三个特点:
1、如果传入的文本内容一样,并且采用hash算法也一样,那么得到的hash值一定是一样的
2、hash值的长度取决于采用的算法,与传入的文本内容的大小无关
3、hash值不可逆
2.2、hashlib模块的使用
import hashlib
# 第一部分
m = hashlib.md5()
m.update('你好'.encode('utf-8'))
m.update('allen'.encode('utf-8'))
m.update('哈哈'.encode('utf-8'))
res = m.hexdigest()
print(res)
# 第二部分
m1 = hashlib.md5()
m1.update('你好allen'.encode('utf-8'))
m1.update('哈'.encode('utf-8'))
m1.update('哈'.encode('utf-8'))
res1 = m1.hexdigest()
print(res1)
# 结论: 以上两部分得到的结果(hash值)是一致的
2.3、利用hashlib模块实现撞库的案例
import hashlib
password_list = ['allen123', 'allexv587', 'allennb123']
pwd_save_dict = {}
def get_pwd_dict(password_list):
"""
将猜测的用户名与加密后的hash值整理到字典中
:param password_list:
:return:
"""
for pwd in password_list:
m = hashlib.md5()
m.update(pwd.encode('utf-8'))
pwd_save_dict.update({pwd: m.hexdigest()})
get_pwd_dict(password_list)
print(pwd_save_dict)
def broken_pwd(pwd_str, pwd_dict):
"""
撞库功能
:param pwd_str:
:param pwd_dict:
:return:
"""
for k, v in pwd_dict.items():
if v == pwd_str:
print('原密码是{}'.format(k))
break
else:
print('不存在')
broken_pwd('fca3ca515d9620851de3ee43fbc05b13', pwd_save_dict)
3、time与datetime模块
3.1、时间有三种格式
import time
# 1、时间戳: 秒数
print(time.time())
# 2、格式化的字符串
time.strftime('%Y-%m-%d %H:%S:%M %p')
time.strftime('%Y-%m-%d %X')
# 3、结构化的时间 => 获取时间的某一部分
time.localtime() # 当地时间 使用更多
time.gmtime() # 世界标准时间
3.2、时间转换
import time
# 时间戳 ---> 格式化的字符串
struct_time = time.localtime(time.time())
res = time.strftime('%Y-%m-%d %H:%M:%S', struct_time)
print(res) # 2020-07-30 14:40:27
# 格式化的字符串 ---> 时间戳
struct_time = time.strptime('2020-07-30 14:40:27', '%Y-%m-%d %H:%M:%S')
res = time.mktime(struct_time)
print(res) # 1596091227.0
# asctime([t]) : 把一个表示时间的元组或者struct_time表示为这种形式:'Sun Jun 20 23:21:05 1993'。
# 如果没有参数,将会将time.localtime()作为参数传入。
print(time.asctime()) # Sun Sep 11 00:43:43 2016
# ctime([secs]) : 把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。如果参数未给或者为
# None的时候,将会默认time.time()为参数。它的作用相当于time.asctime(time.localtime(secs))。
print(time.ctime()) # Sun Sep 11 00:46:38 2016
print(time.ctime(time.time())) # Sun Sep 11 00:46:38 2016
import time
# asctime
res = time.asctime() # 默认传递time.localtime(),等同于res = time.asctime(time.localtime())
print(res) # Thu Jul 30 14:47:54 2020
# ctime
res = time.ctime(time.time())
print(res) # Thu Jul 30 14:47:54 2020
# time.sleep(n)
线程推迟指定的时间运行,单位为秒
time.sleep(2)
3.3、datetime模块
import datetime
res = datetime.datetime.now()
print(res)
# 获取3天后的时间
res = datetime.datetime.now() + datetime.timedelta(days=3)
print(res)
# 获取3小时前的时间
res = datetime.datetime.now() + datetime.timedelta(hours=-3)
print(res)
# 根据时间戳获取年月日
res = datetime.date.fromtimestamp(time.time())
print(res) # 2020-07-30
# 根据时间戳获取年月日时分秒
res = datetime.datetime.fromtimestamp(time.time())
print(res) # 2020-07-30 14:58:08.334841
# 替换时间格式化时间中的部分
res = datetime.datetime.now()
print(res)
new_res = res.replace(year=1995, hour=8)
print(new_res)
3.4、利用time模块实现打印进度条
import time
def progress(percent):
if percent > 1:
percent = 1
print('\r[%-50s] %d%%' % ('#' * int(percent * 50), int(percent * 100)), end='')
total_size = 155000
recv_size = 0
while recv_size < total_size:
time.sleep(0.1)
recv_size += 1024
percent = recv_size / total_size
progress(percent)
4、random模块
4.1、random基本使用
import random
print(random.random()) # (0,1)----float 大于0且小于1之间的小数
print(random.randint(1, 3)) # [1,3] 大于等于1且小于等于3之间的整数
print(random.randrange(1, 3)) # [1,3) 大于等于1且小于3之间的整数
print(random.choice([1, 'a', ['b', 2, 3]])) # 1或者'a'或者['b', 2, 3]
print(random.sample([1, 2, 3, ['a', 'b'], ['1', '2']], 2)) # 列表元素任意2个组合
print(random.uniform(1, 3)) # 大于1小于3的小数,如1.927109612082716
item = [1, 2, 3, 4, 5, 6]
random.shuffle(item) # 打乱item的顺序,相当于"洗牌"
print(item)
4.2、利用random模块实现验证码
def make_code(count=4):
"""
生成随机验证码
:param count:
:return:
"""
code_msg = ''
for x in range(count):
s1 = str(random.randint(0, 9))
s2 = chr(random.randint(65, 90))
code = random.choice([s1, s2])
code_msg += code
return code_msg
print(make_code(6))
5、os模块
os模块是与操作系统交互的一个接口
os.getcwd() # 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") # 改变当前脚本工作目录;相当于shell下cd
os.curdir # 返回当前目录: ('.')
os.pardir # 获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2') # 可生成多层递归目录
os.removedirs('dirname1') # 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') # 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') # 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') # 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() # 删除一个文件
os.rename("oldname","newname") # 重命名文件/目录
os.stat('path/filename') # 获取文件/目录信息
os.sep # 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep # 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep # 输出用于分割文件路径的字符串 win下为;,Linux下为:
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所指向的文件或者目录的最后修改时间
os.path.getsize(path) # 返回path的大小
6、sys模块
6.1、sys基本使用
sys.argv # 命令行参数List,第一个元素是程序本身路径
sys.exit(n) # 退出程序,正常退出时exit(0)
sys.version # 获取Python解释程序的版本信息
sys.maxint # 最大的Int值
sys.path # 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform # 返回操作系统平台名称
6.2、利用sys.argv实现文件拷贝
# server.py
import sys
import os
args1 = sys.argv[1]
args2 = sys.argv[2]
if os.path.exists(args1):
with open(r'{}'.format(args1), mode='rb') as fp1, \
open(r'{}'.format(args2), mode='wb') as fp2:
for line in fp1:
fp2.write(line)
print('拷贝成功')
# cmd
python3 server.py 源文件路径 目标文件路径
7、subprocess模块
import subprocess
obj = subprocess.Popen('dir', shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
success_res = obj.stdout.read().decode('gbk') # 正确信息
print(success_res)
error_res = obj.stderr.read().decode('gbk') # 错误信息
print(error_res)
8、shutil模块
高级的 文件、文件夹、压缩包 处理模块
# (1) shutil.copyfileobj(fsrc, fdst[, length])
# 将文件内容拷贝到另一个文件中
import shutil
shutil.copyfileobj(open('config.ini', mode='r'), open('xxx.ini', mode='w'))
# (2) shutil.copyfile(src, dst)
# 拷贝文件
import shutil
shutil.copyfile('config.ini', 'xxx.ini')
# (3) shutil.copymode(src, dst)
# 仅拷贝权限。内容、组、用户均不变
import shutil
shutil.copymode('f1.log', 'f2.log') # 目标文件必须存在
# (4) shutil.copystat(src, dst)
# 仅拷贝状态的信息,包括:mode bits, atime, mtime, flags
import shutil
shutil.copystat('f1.log', 'f2.log') #目标文件必须存在
# (5) shutil.copy(src, dst)
# 拷贝文件和权限
import shutil
shutil.copy('f1.log', 'f2.log')
# (6) shutil.copy2(src, dst)
# 拷贝文件和状态信息
import shutil
shutil.copy2('f1.log', 'f2.log')
# (7) shutil.ignore_patterns(*patterns)
# shutil.copytree(src, dst, symlinks=False, ignore=None)
# 递归的去拷贝文件夹
import shutil
shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) # 目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
# (8) shutil.rmtree(path[, ignore_errors[, onerror]])
# 递归的去删除文件
import shutil
shutil.rmtree('folder1')
# (9) shutil.move(src, dst)
# 递归的去移动文件,它类似mv命令,其实就是重命名
import shutil
shutil.move('folder1', 'folder3')
# (10) shutil.make_archive(base_name, format,...)
# 创建压缩包并返回文件路径,例如:zip、tar
# 创建压缩包并返回文件路径,例如:zip、tar
# base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
# 如 data_bak =>保存至当前路径
# 如 /tmp/data_bak =>保存至/tmp/
# format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
# root_dir: 要压缩的文件夹路径(默认当前目录)
# owner: 用户,默认当前用户
# group: 组,默认当前组
# logger: 用于记录日志,通常是logging.Logger对象
# (11) zipfile压缩解压缩
import zipfile
# 压缩
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close()
# 解压
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall(path='.')
z.close()
# (12) tarfile压缩解压缩
import tarfile
# 压缩
t=tarfile.open('/tmp/allen.tar','w')
t.add('/test1/a.py',arcname='a.bak')
t.add('/test1/b.py',arcname='b.bak')
t.close()
# 解压
t=tarfile.open('/tmp/allen.tar','r')
t.extractall('/allen')
t.close()
9、shelve模块
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型
import shelve
f = shelve.open(r'a.txt')
f['info'] = {'name': 'allen', 'age': 18}
print(f['info']['name'])
f.close()
10、xml模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank updated="yes">5</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank updated="yes">69</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
11、configparser模块:
# conf.ini
[section1]
user = 'allen'
age : 18
gender = 'male'
salary = 19.5
is_admin = 1
[section2]
user = 'lisi'
import configparser
config = configparser.ConfigParser()
config.read('config.ini')
print(config.sections()) # ['section1', 'section2']
print(config.options('section1')) # ['user', 'age', 'gender', 'salary', 'is_admin']
print(config.items('section1')) # [('user', "'allen'"), ('age', '18'), ('gender', "'male'"), ('salary', '19.5'), ('is_admin', '1')]
res = config.get('section1', 'salary')
print(res, type(res))
res = config.getfloat('section1', 'salary')
print(res, type(res))
print(config.getboolean('section1', 'is_admin'))
res = config.getint('section1', 'age')
print(res, type(res))
12、logging模块
12.1、日志级别
CRITICAL = 50 # FATAL = CRITICAL
ERROR = 40
WARNING = 30 # WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0 # 不设置
12.2、默认级别为warning,默认打印到终端
import logging
logging.debug('调试debug')
logging.info('消息info')
logging.warning('警告warn')
logging.error('错误error')
logging.critical('严重critical')
'''
WARNING:root:警告warn
ERROR:root:错误error
CRITICAL:root:严重critical
'''
12.3、日志级别与配置
import logging
# 一: 日志配置
logging.basicConfig(
# 1、日志输出位置:1、终端 2、文件
# filename='access.log', # 不指定,默认打印到终端
# 2、日志格式
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
# 3、时间格式
datefmt='%Y-%m-%d %H:%M:%S %p',
# 4、日志级别
# critical => 50
# error => 40
# warning => 30
# info => 20
# debug => 10
level=30,
)
# 二: 输出日志
logging.debug('调试debug')
logging.info('消息info')
logging.warning('警告warn')
logging.error('错误error')
logging.critical('严重critical')
'''
# 注意下面的root是默认的日志名字
WARNING:root:警告warn
ERROR:root:错误error
CRITICAL:root:严重critical
'''
12.4、日志配置字典
"""
logging配置
"""
import os
# 1、定义三种日志输出格式,日志中可能用到的格式化串如下
# %(name)s Logger的名字
# %(levelno)s 数字形式的日志级别
# %(levelname)s 文本形式的日志级别
# %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
# %(filename)s 调用日志输出函数的模块的文件名
# %(module)s 调用日志输出函数的模块名
# %(funcName)s 调用日志输出函数的函数名
# %(lineno)d 调用日志输出函数的语句所在的代码行
# %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
# %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
# %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
# %(thread)d 线程ID。可能没有
# %(threadName)s 线程名。可能没有
# %(process)d 进程ID。可能没有
# %(message)s用户输出的消息
# 2、强调: 其中的%(name)s为getlogger时指定的名字
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
'[%(levelname)s][%(message)s]'
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
test_format = '%(asctime)s] %(message)s'
# 3、日志配置字典
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
'test': {
'format': test_format
},
},
'filters': {},
'handlers': {
# 打印到终端的日志
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'simple'
},
# 打印到文件的日志,收集info及以上的日志
'default': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,日志轮转
'formatter': 'standard',
# 可以定制日志文件路径
# BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # log文件的目录
# LOG_PATH = os.path.join(BASE_DIR,'a1.log')
'filename': 'a1.log', # 日志文件
'maxBytes': 1024*1024*5, # 日志大小 5M
'backupCount': 5,
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
'other': {
'level': 'DEBUG',
'class': 'logging.FileHandler', # 保存到文件
'formatter': 'test',
'filename': 'a2.log',
'encoding': 'utf-8',
},
},
'loggers': {
# logging.getLogger(__name__)拿到的logger配置
'': {
'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'level': 'DEBUG', # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制)
'propagate': False, # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会一份日志向上层层传递
},
'专门的采集': {
'handlers': ['other',],
'level': 'DEBUG',
'propagate': False,
},
},
}
12.5、使用
import settings
# 强调
# 1、logging是一个包,需要使用其下的config、getLogger,可以如下导入
# from logging import config
# from logging import getLogger
# 2、也可以使用如下导入
import logging.config # 这样连同logging.getLogger都一起导入了,然后使用前缀logging.config.
# 3、加载配置
logging.config.dictConfig(settings.LOGGING_DIC)
# 4、输出日志
logger1=logging.getLogger('用户交易')
logger1.info('allen转账3亿人民币')
# logger2=logging.getLogger('专门的采集') # 名字传入的必须是'专门的采集',与LOGGING_DIC中的配置唯一对应
# logger2.debug('专门采集的日志')
13、re模块
13.1、什么是正则表达式
由一系列特殊字符拼接而成的表达式/规则,该表达式用于从一个大字符串中匹配出符合规则的子字符串
import re
13.2、常用模式一览表
13.3、w、\W
import re
print(re.findall('\w', '你好ls 12*&) _')) # ['你', '好', 'l', 's', '1', '2', '_']
print(re.findall('\W', '你好jx 12*&) _')) # [' ', '*', '&', ')', ' ']
13.4、\s、\S
import re
print(re.findall('\s','你好\rbarry*(_ \t \n')) # ['\r', ' ', '\t', ' ', '\n']
print(re.findall('\S','你好\rbarry*(_ \t \n')) # ['你', '好', 'b', 'a', 'r', 'r', 'y', '*', '(', '_']
13.5、\d、\D
import re
print(re.findall('\d', '1234567890 allen *(_')) # ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
print(re.findall('\D', '1234567890 allen *(_')) # [' ', 'a', 'l', 'l', 'e', 'n', ' ', '*', '(', '_']
13.6、\A、^
import re
print(re.findall('\Ahel','hello 你好世界 -_- 666')) # ['hel']
print(re.findall('^hel','hello 你好世界 -_- 666')) # ['hel']
13.7、\Z、$
import re
print(re.findall('666\Z', 'hello 你好世界 *-_-* \n666')) # ['666']
print(re.findall('666$', 'hello 你好世界 *-_-* \n666')) # ['666']
13.8、\n、\t
import re
print(re.findall('\n','hello \n 你好世界 \t*-_-*\t \n666')) # ['\n', '\n']
print(re.findall('\t','hello \n 你好世界 \t*-_-*\t \n666')) # ['\t', '\t']
13.9、重复匹配
# . ? * + {m,n} .* .*?
# . 匹配任意字符,除了换行符(re.DOTALL 这个参数可以匹配\n)。
print(re.findall('a.b', 'ab aab a*b a2b a牛b a\nb')) # ['aab', 'a*b', 'a2b', 'a牛b']
print(re.findall('a.b', 'ab aab a*b a2b a牛b a\nb', re.DOTALL)) # ['aab', 'a*b', 'a2b', 'a牛b']
# ?匹配0个或者1个由左边字符定义的片段。
print(re.findall('a?b', 'ab aab abb aaaab a牛b aba**b')) # ['ab', 'ab', 'ab', 'b', 'ab', 'b', 'ab', 'b']
# * 匹配0个或者多个左边字符表达式。 满足贪婪匹配 @@
print(re.findall('a*b', 'ab aab aaab abbb')) # ['ab', 'aab', 'aaab', 'ab', 'b', 'b']
print(re.findall('ab*', 'ab aab aaab abbbbb')) # ['ab', 'a', 'ab', 'a', 'a', 'ab', 'abbbbb']
# + 匹配1个或者多个左边字符表达式。 满足贪婪匹配 @@
print(re.findall('a+b', 'ab aab aaab abbb')) # ['ab', 'aab', 'aaab', 'ab']
# {m,n} 匹配m个至n个左边字符表达式。 满足贪婪匹配 @@
print(re.findall('a{2,4}b', 'ab aab aaab aaaaabb')) # ['aab', 'aaab']
# .* 贪婪匹配 从头到尾.
print(re.findall('a.*b', 'ab aab a*()b')) # ['ab aab a*()b']
# .*? 此时的?不是对左边的字符进行0次或者1次的匹配,
# 而只是针对.*这种贪婪匹配的模式进行一种限定:告知他要遵从非贪婪匹配 推荐使用!
print(re.findall('a.*?b', 'ab a1b a*()b, aaaaaab')) # ['ab', 'a1b', 'a*()b']
# []: 括号中可以放任意一个字符,一个中括号代表一个字符
# - 在[]中表示范围,如果想要匹配上- 那么这个-符号不能放在中间.
# ^ 在[]中表示取反的意思.
print(re.findall('a.b', 'a1b a3b aeb a*b arb a_b')) # ['a1b', 'a3b', 'a4b', 'a*b', 'arb', 'a_b']
print(re.findall('a[abc]b', 'aab abb acb adb afb a_b')) # ['aab', 'abb', 'acb']
print(re.findall('a[0-9]b', 'a1b a3b aeb a*b arb a_b')) # ['a1b', 'a3b']
print(re.findall('a[a-z]b', 'a1b a3b aeb a*b arb a_b')) # ['aeb', 'arb']
print(re.findall('a[a-zA-Z]b', 'aAb aWb aeb a*b arb a_b')) # ['aAb', 'aWb', 'aeb', 'arb']
print(re.findall('a[0-9][0-9]b', 'a11b a12b a34b a*b arb a_b')) # ['a11b', 'a12b', 'a34b']
print(re.findall('a[*-+]b', 'a-b a*b a+b a/b a6b')) # ['a*b', 'a+b']
# - 在[]中表示范围,如果想要匹配上- 那么这个-符号不能放在中间.
print(re.findall('a[-*+]b', 'a-b a*b a+b a/b a6b')) # ['a-b', 'a*b', 'a+b']
print(re.findall('a[^a-z]b', 'acb adb a3b a*b')) # ['a3b', 'a*b']
13.10、分组
# () 制定一个规则,将满足规则的结果匹配出来
print(re.findall('(.*?)_all', 'allen_all lily_all lucy_all')) # ['allen', ' lily', ' lucy']]
# 应用举例:
print(re.findall('href="(.*?)"','<a href="http://www.baidu.com">点击</a>'))#['http://www.baidu.com']
13.11、或
# | 匹配 左边或者右边
print(re.findall('allen|丽丽|lucy', 'allen李白lucyalllen李白白')) # ['allen', 'lucy']
print(re.findall('compan(y|ies)','Too many companies have gone bankrupt, and the next one is my company')) # ['ies', 'y']
print(re.findall('compan(?:y|ies)','Too many companies have gone bankrupt, and the next one is my company')) # ['companies', 'company']
# 分组() 中加入?: 表示将整体匹配出来而不只是()里面的内容
13.12、常用方法
# 1 findall 全部找到返回一个列表。
print(re.findall('a', 'allenisaboy')) # ['a', 'a']
# 2 search 只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
print(re.search('allen|lucy', 'allen lucy lucy 中国')) # <re.Match object; span=(0, 5), match='allen'>
print(re.search('allen', 'allen lucy lucy 中国').group()) # allen
# 3 match:None,同search,不过在字符串开始处进行匹配,完全可以用search+^代替match
print(re.match('allen', 'allen lucy lucy 中国')) # <re.Match object; span=(0, 5), match='allen'>
print(re.match('allen', 'allen lucy lucy 中国').group()) # allen
# 4 split 分割 可按照任意分割符进行分割
print(re.split('[:,;]', 'allen:lucy,lucy:中国')) # ['allen', 'lucy', 'lucy', '中国']
# 5 重复使用
obj = re.compile('\d{2}')
print(obj.search('abc123eeee').group()) # 12
print(obj.findall('abc123eeee')) # ['12'],重用了obj
# import re
ret = re.finditer('\d', 'ds3sy4784a') # finditer返回一个存放匹配结果的迭代器
print(ret) # <callable_iterator object at 0x000001CC6B398670>
print(next(ret).group()) # 查看第一个结果
print(next(ret).group()) # 查看第二个结果
print([i.group() for i in ret]) # 查看剩余的左右结果
14、struct模块(解决粘包现象时会使用)
# 该模块可以把一个类型,如数字,转成固定长度的bytes类型
import struct
res = struct.pack('i',12345)
print(res,len(res),type(res)) # 长度是4
res2 = struct.pack('i',12345111)
print(res,len(res),type(res2)) # 长度也是4
unpack_res =struct.unpack('i',res2)
print(unpack_res) # (12345111,)
print(unpack_res[0]) # 12345111
15、paramiko模块
# 该模块可以在本地远程控制linux服务器
import paramiko
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='192.168.12.80', port=22, username='root', password='root')
# 执行命令
stdin, stdout, stderr = ssh.exec_command('cd / && ls -al')
# 获取命令结果
result = stdout.read()
# 关闭连接
ssh.close()
print(result.decode('utf-8'))