-
collections模块
#namedtuple是collections模块提供的带名字的元组 from collections import namedtuple # 导入namedtuple # 定义一种namedtuple类型,传入两个参数,一个是类型名,一个是元组各个值的名称 point = namedtuple('Point',['x','y']) p = point(1,2) # 创建一个namedtuple对象 print(p.x) # 可以使用该形式调用元组中的各个值 print(p.y)
使用列表储存数据时,按索引访问数据的速度很快,但是对列表进行插入和删除操作却很慢。因为列表时线性储存,当数据量很大时,插入和删除会变得很慢。
deque是为了实现插入和删除操作的双向列表,适用于队列和栈
from collections import deque # 从collections模块导入deque d = deque() # 创建一个双向队列 d.append('a') # 在双向队列的右边添加一个值 d.append('b') # 在双向队列的右边添加一个值 d.appendleft('c') # 在双向队列的左边添加一个值 print(d.pop()) # 删除双向队列左边的一个值,并返回该值 print(d.popleft()) # 删除双向队列右边的一个值,并返回该值
使用dict数据类型时,key是无序的,在对dict进行迭代时无法确定key的顺序
可以使用OrderedDict创建一个有序的字典,有序字典的顺序是key添加进字典的顺序
from collections import OrderedDict # 导入OrderedDict od = OrderedDict([('b',1),('c',2),('d',3)]) # 创建一个有序字典 print(od) # 结果为OrderedDict([('b', 1), ('c', 2), ('d', 3)]) od['a'] = 4 # 在有序字典中插入一个键值对 for i in od: # 对字典进行迭代会按照key插入字典的顺序进行 print(i)
dic = dict([('a',1),('b',2),('c',3)]) # 这也是定义一个普通字典的方法
有时候我们希望字典的每个key对应的值有一个默认值,可以使用defaultdict做到对每个key对应的值设置一个默认值
from collections import defaultdict # 导入defaultdict dd = defaultdict(list) # 创建一个有默认键值的字典 print(dd['a']) # 虽然字典中没有a这个key,但是不会报错而是会输出默认键值[] dd['b'].append(1) # 可以直接对默认键值进行操作 print(dd) #结果是defaultdict(<class 'list'>, {'b': [1], 'a': []})
Counter是用来计算容器中各个值得个数
from collections import Counter # 导入Counter模块 a = '122333444455555' print(Counter(a)) # 对容器变量中的各个值得个数进行计数
-
时间模块
可以使用time模块对时间进行相关操作
#常用方法 import time time.sleep(10) # 让程序睡一会 time.time() # 获得当前时间的时间戳
在python中有三种表示时间的方式时间戳,机构化时间,格式化时间。
时间戳时间是个程序看的,它是1970年1月1日以来按秒计算的偏移量
结构化时间是把时间的各个属性储存在一个类似命名元组的数据中
格式化时间是将数据按照人能看懂的方式储存在一个字符串中
python中时间日期格式化符号:
%y 两位数的年份表示(00-99) %Y 四位数的年份表示(000-9999) %m 月份(01-12) %d 月内中的一天(0-31) %H 24小时制小时数(0-23) %I 12小时制小时数(01-12) %M 分钟数(00=59) %S 秒(00-59) %a 本地简化星期名称 %A 本地完整星期名称 %b 本地简化的月份名称 %B 本地完整的月份名称 %c 本地相应的日期表示和时间表示 %j 年内的一天(001-366) %p 本地A.M.或P.M.的等价符 %U 一年中的星期数(00-53)星期天为星期的开始 %w 星期(0-6),星期天为星期的开始 %W 一年中的星期数(00-53)星期一为星期的开始 %x 本地相应的日期表示 %X 本地相应的时间表示 %Z 当前时区的名称 %% %号本身
import time # 导入时间模块 ret = time.time() # 获得当前时间戳时间 print(ret) # 结果为1554637911.832636 ret = time.localtime() # 获得当前结构化时间 print(ret) # 结果为time.struct_time(tm_year=2019, tm_mon=4, tm_mday=7, tm_hour=19, tm_min=51, tm_sec=51, tm_wday=6, tm_yday=97, tm_isdst=0) ret = time.strftime('%Y/%m/%d %H:%M:%S') # 获得按指定格式输出的格式化时间 print(ret) # 结果为2019/04/07 19:53:41
print(time.asctime()) # 以一个固定的格式输出一个格式化时间
索引(Index) | 属性(Attribute) | 值(Values) |
---|---|---|
0 | tm_year(年) | 比如2011 |
1 | tm_mon(月) | 1 - 12 |
2 | tm_mday(日) | 1 - 31 |
3 | tm_hour(时) |
0 - 23 |
4 | tm_min(分) | 0 - 59 |
5 | tm_sec(秒) | 0 - 60 |
6 | tm_wday(weekday) | 0 - 6(0表示周一) |
7 | tm_yday(一年中的第几天) | 1 - 366 |
8 | tm_isdst(是否是夏令时) | 默认为0 |
时间戳时间和结构化时间之间可以相互转化,格式化时间和结构化时间之间也可以相互转化,时间戳时间和格式化时间之间的转换需要以结构化时间为中介进行
import time struct_time = time.localtime(1600000000) # 将时间戳时间转化为格式化时间 struct_time1 = time.gmtime(1600000000) # 将时间戳时间转化为英国伦敦的格式化时间 print(struct_time) #结果为time.struct_time(tm_year=2020, tm_mon=9, tm_mday=13, tm_hour=20, tm_min=26, tm_sec=40, tm_wday=6, tm_yday=257, tm_isdst=0) print(struct_time1) #结果为time.struct_time(tm_year=2020, tm_mon=9, tm_mday=13, tm_hour=12, tm_min=26, tm_sec=40, tm_wday=6, tm_yday=257, tm_isdst=0) stamptime = time.mktime(struct_time) # 将结构化时间转化为时间戳时间 print(stamptime) # 结果为1600000000.0 format_time = time.strftime('%y/%m/%d %H:%M:%S',struct_time) # 将结构化时间转化为格式化时间 print(format_time) # 结果为20/09/13 20:26:40 struct_time = time.strptime('70/01/01 08:00:00','%y/%m/%d %H:%M:%S') # 将格式化时间转化为结构化时间 print(struct_time) #结果为time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=8, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=-1) #时间戳时间与格式化时间之间的转换需要以结构化时间为中介进行 stamptime = 0 struct_time = time.localtime(stamptime) # 将时间戳时间转化为结构化时间 format_time = time.strftime('%y/%m/%d %H:%M:%S',struct_time) # 将结构化时间转为格式化时间 print(format_time) # 结果为70/01/01 08:00:00 format_time = '70/01/01 08:00:00' struct_time = time.strptime(format_time,'%y/%m/%d %H:%M:%S') # 将格式化时间转为结构化时间 stamptime = time.mktime(struct_time) # 将结构化时间转化为时间戳时间 print(stamptime) # 结构为0.0
#计算时间差 import time struct_nowtime = time.localtime() struct_passtime = time.localtime(0) d_year = struct_nowtime.tm_year - struct_passtime.tm_year d_mon = struct_nowtime.tm_mon - struct_passtime.tm_mon d_mday = struct_nowtime.tm_mday - struct_passtime.tm_mday d_hour = struct_nowtime.tm_hour - struct_passtime.tm_hour d_min = struct_nowtime.tm_min - struct_passtime.tm_min d_sec = struct_nowtime.tm_sec - struct_passtime.tm_sec st = '从1970年1月1日至今过去了{}年{}月{}天{}小时{}分钟{}秒'.format(d_year,d_mon,d_mday,d_hour,d_min,d_sec) print(st)
-
random模块
import random # 导入random模块 ret = random.random() # 生成大于0且小于1的随机小数 print(ret) n,m = 2,5 ret = random.uniform(n,m) # 生成大于n小于m的随机小数 print(ret) ret = random.randint(n,m) # 生成大于n小于m的随机整数 print(ret) ret = random.randrange(0,10,2) # 生成0至10之间奇数的随机数 print(ret) ret = random.choice(['a',2,[1,2]]) # 从列表中随机选择一个值 print(ret) ret = random.sample([1,'a',[1,2],{'a':1},(3,4)],n) # 从列表中随机取n个值 print(ret) item = [1,2,3,4,5] ret = random.shuffle(item) # 打乱列表次序 print(item)
#生成一个随机验证码 import random digit_c = list(range(48,58)) + list(range(97,123)) + list(range(65,91)) check_d = random.sample(digit_c,4) check_c = map(lambda x:chr(x),check_d) check_str = '' for i in check_c: check_str += i print(check_str)
-
os模块
os模块是与操作系统交互的接口
import os # 导入os模块 os.makedirs('directory1/directory2') # 可生成多层递归目录 os.removedirs('directory1/directory2') # 若目录为空则删除,并返回上一级目录,如果也为空则也删除 os.mkdir('directory') # 生成单级目录 os.rmdir('directory') # 若单级目录为空则删除,如果不为空则无法删除并报错 print(os.listdir('.')) # 列出指定目录下的所有文件和子目录,包括隐藏文件 os.rename('test','test1') # 重命名一个文件 os.remove('test1') # 删除指定文件 print(os.stat('test')) # 获取文件、目录的信息 import os os.system('dir') # 运行shell命令,并直接显示 print(os.popen('dir').read()) # 运行shell命令获取执行结果 print(os.getcwd()) # 获取当前工作目录,即当前python脚本工作路径 os.chdir('directory') # 更改当前工作目录 #os.path path = 'D:pppday' print(os.path.abspath('.')) # 返回path规范化的绝对路径 print(os.path.split(path)) # 将path分割成目录和文件名二元组返回 print(os.path.dirname(path)) # 返回path的目录,其实就是os.path.split()的第一个元素 print(os.path.basename(path)) # 返回path的最后一个文件名,如果以结尾则返回空值。 print(os.path.exists(path)) # 如果path存在则返回True,如果不存在则返回False print(os.path.isabs(path)) # 如果是绝对路径则返回True,否则返回False print(os.path.isfile(path)) # 如果path是一个文件则返回True,否则返回False print(os.path.isdir(path)) # 如果path是一个存在的目录就返回True,否则返回False print(os.path.join('D:ppp','day')) # 将多个路径组合返回 print(os.path.getatime(path)) # 返回path所指向的目录或文件最后访问时间 print(os.path.getmtime(path)) # 返回path所指向的文件或者目录最后修改的时间 print(os.path.getsize(path)) # 返回path所指向的文件或者目录的大小(指向目录时计算的大小不准确)
stat 结构: st_mode: inode 保护模式 st_ino: inode 节点号。 st_dev: inode 驻留的设备。 st_nlink: inode 的链接数。 st_uid: 所有者的用户ID。 st_gid: 所有者的组ID。 st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。 st_atime: 上次访问的时间。 st_mtime: 最后一次修改的时间。 st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。
os.sep 输出操作系统特定的路径分隔符,win下为"\",Linux下为"/" os.linesep 输出当前平台使用的行终止符,win下为" ",Linux下为" " os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为: os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
-
sys模块
sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys.exit(1) sys.version 获取Python解释程序的版本信息 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform 返回操作系统平台名称
-
序列化模块
在进行储存和网络传输的过程中需要将各种数据类型转化成字符串类型进行储存和传输。将字典和列表等各种数据类型转化为字符串的过程成为序列化,而将字符串还原为字典列表等数据类型的过程称为反序列化。
有json、pickle、shelve三个模块可以完成数据的序列化和反序列化
json所生成的序列化文件是一种通用的语言,可以被各种程序设计语言使用,但是由于是通用的所以只有少量一部分数据类型能够被json序列化
import json # 导入json模块 dic = {'a':1,'b':2,'c':3,'d':4} # json能将字典和字符串类型的数据序列化 print(type(dic),dic) # 字典类型的数据<class 'dict'> {'b': 2, 'a': 1, 'd': 4, 'c': 3} st_d = json.dumps(dic) # 使用dumps将数据序列化并存放在内存中 print(type(st_d),st_d) # 得到的是一个字符串类型的数据 <class 'str'> {"b": 2, "a": 1, "d": 4, "c": 3} dic1 = json.loads(st_d) # 利用loads将字符串数据反序列化为原数据类型 print(type(dic1),dic1) # 结果为<class 'dict'> {'b': 2, 'c': 3, 'a': 1, 'd': 4} with open('dic_packet','w',encoding='utf-8') as fw: json.dump(dic,fw) # 使用dump将数据序列化储存在文件中,使用该方法一个文件只能储存一个数据 with open('dic_packet','r',encoding='utf-8') as fr: st_d = json.load(fr) # 使用load将储存在文件中的数据反序列化为原数据类型 print(type(st_d),st_d) # 结果为<class 'dict'> {'a': 1, 'c': 3, 'b': 2, 'd': 4}
# 间接使用json实现在一个文件中储存多个数据 import json li_dic = [{'k1':'安徽'},{'k1':'北京'},{'k3':'上海'}] with open('dic_picket','w',encoding='utf-8') as fw: for i in li_dic: json.dump(i,fw,ensure_ascii=False) # ensure_ascii可以设置是否在文件中显示中文 fw.write(' ') dic_li = [] with open('dic_picket','r',encoding='utf-8') as fr: for i in fr: dic_li.append(json.loads(i.strip())) print(dic_li)
其他参数说明 Serialize obj to a JSON formatted str.(字符串表示的json对象) Skipkeys:默认值是False,如果dict的keys内的数据不是python的基本类型(str,unicode,int,long,float,bool,None),设置为False时,就会报TypeError的错误。此时设置成True,则会跳过这类key ensure_ascii:,当它为True的时候,所有非ASCII码字符显示为uXXXX序列,只需在dump时将ensure_ascii设置为False即可,此时存入json的中文即可正常显示。) If check_circular is false, then the circular reference check for container types will be skipped and a circular reference will result in an OverflowError (or worse). If allow_nan is false, then it will be a ValueError to serialize out of range float values (nan, inf, -inf) in strict compliance of the JSON specification, instead of using the JavaScript equivalents (NaN, Infinity, -Infinity). indent:应该是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。 default(obj) is a function that should return a serializable version of obj or raise TypeError. The default simply raises TypeError. sort_keys:将数据根据keys的值进行排序。 To use a custom JSONEncoder subclass (e.g. one that overrides the .default() method to serialize additional types), specify it with the cls kwarg; otherwise JSONEncoder is used.
import json data = {'username':['李华','二愣子'],'sex':'male','age':16} json_dic2 = json.dumps(data,sort_keys=True,indent=2,separators=(',',':'),ensure_ascii=False) print(json_dic2)
有些数据类型不能被json序列化,而且并序列化后的文件不需要被多种程序语言使用。pickle模块可以完成所有的python数据类型的序列化,一些数据类型需要相应的模块的支持。
import pickle from collections import namedtuple # pickle模块的使用与json模块类似 address = namedtuple('address',['key','local']) #pickle模块支持对命名元组进行序列化 tu_li = [address('k1','河南'),address('k2','湖南'),address('k3','江苏')] print(tu_li) with open('tu_packet','wb') as fw: for i in tu_li: pickle.dump(i,fw) # pickle直接支持多个数据放在同一个文件中 namedtu_li = [] with open('tu_packet','rb') as fr: for i in range(3): namedtu_li.append(pickle.load(fr)) print(namedtu_li)
shelve模块也能对python的任意数据类型进行序列化,据说非常方便,但是由于是新的模块大家还没有用习惯
import shelve f1 = shelve.open('dic_packet',writeback=True) # 打开一个shelve writeback决定是否可以对文件进行修改 f1['key1'] = {'k1':1} # 可以直接对句柄进行操作 f1['key2'] = {'k2':2} print(f1['key1']) print(f1['key2']) f1.close()
-
re模块
re模块是python中使用正则表达式的模块。
正则表达式在匹配字符串中很好用,如果使用判断语句匹配会把程序搞得很复杂,且有时候实现不了。使用正则表达式匹配字符串非常的方便。在爬虫中有很广泛的运用。
字符组 : [字符组] 在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[]表示 字符分为很多类,比如数字、字母、标点等等。 假如你现在要求一个位置"只能出现一个数字",那么这个位置上的字符只能是0、1、2...9这10个数之一。
正则 |
待匹配字符 |
匹配 |
说明 |
[0123456789] |
8 |
True |
在一个字符组里枚举合法的所有字符,字符组里的任意一个字符 |
[0123456789] |
a |
False |
由于字符组中没有"a"字符,所以不能匹配 |
[0-9] |
7 |
True |
也可以用-表示范围,[0-9]就和[0123456789]是一个意思 |
[a-z] |
s |
True |
同样的如果要匹配所有的小写字母,直接用[a-z]就可以表示 |
[A-Z] |
B |
True |
[A-Z]就表示所有的大写字母 |
[0-9a-fA-F] |
e |
True |
可以匹配数字,大小写形式的a~f,用来验证十六进制字符 |
字符:
元字符 |
匹配内容 |
. | 匹配除换行符以外的任意字符 |
w | 匹配字母或数字或下划线 |
s | 匹配任意的空白符 |
d | 匹配数字 |
匹配一个换行符 | |
匹配一个制表符 | |
匹配一个单词的结尾 | |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结尾 |
W |
匹配非字母或数字或下划线 |
D |
匹配非数字 |
S |
匹配非空白符 |
a|b |
匹配字符a或字符b |
() |
匹配括号内的表达式,也表示一个组 |
[...] |
匹配字符组中的字符 |
[^...] |
匹配除了字符组中字符的所有字符 |
量词:
量词 |
用法说明 |
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
正则表达式默认是贪婪匹配,也就是会尽可能多的匹配字符。 可以使用?设置为非贪婪匹配,这时会尽可能少的匹配字符串 在字符集[]中使用[^……]表示非,匹配没有出现在字符集中的字符 可以使用()对字符组进行分组,方便对字符组进行批量处理
有时需要匹配一些在正则表达式中有特殊意义的字符,如*?等,这时可以使用转移符取消字符的特殊意义
re模块
import re ret = re.findall('a', 'eva egon yuan') # 返回所有满足匹配条件的结果,放在列表里 print(ret) #结果 : ['a', 'a'] ret = re.search('a', 'eva egon yuan').group() print(ret) #结果 : 'a' # 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以 # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。 ret = re.match('a', 'abc').group() # 同search,不过尽在字符串开始处进行匹配 print(ret) #结果 : 'a' ret = re.split('[ab]', 'abcd') # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割 print(ret) # ['', '', 'cd'] ret = re.sub('d', 'H', 'eva3egon4yuan4', 1)#将数字替换成'H',参数1表示只替换1个 print(ret) #evaHegon4yuan4 ret = re.subn('d', 'H', 'eva3egon4yuan4')#将数字替换成'H',返回元组(替换的结果,替换了多少次) print(ret) obj = re.compile('d{3}') #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字 ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串 print(ret.group()) #结果 : 123 import re ret = re.finditer('d', 'ds3sy4784a') #finditer返回一个存放匹配结果的迭代器 print(ret) # <callable_iterator object at 0x10195f940> print(next(ret).group()) #查看第一个结果 print(next(ret).group()) #查看第二个结果 print([i.group() for i in ret]) #查看剩余的左右结果
import re ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com') print(ret) # ['oldboy'] 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可 ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com') print(ret) # ['www.oldboy.com']
ret=re.split("d+","eva3egon4yuan") print(ret) #结果 : ['eva', 'egon', 'yuan'] ret=re.split("(d+)","eva3egon4yuan") print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan'] #在匹配部分加上()之后所切出的结果是不同的, #没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项, #这个在某些需要保留匹配部分的使用过程是非常重要的。