Tiny_Lu
不忘初心

Day 17 包/time/datetime/random/hashlib/hmac/typing/requests/re模块

什么是包

包就是模块,也是用来导入的

包的本质就是内含带有.py文件的文件夹

为什么要有包

随着文件越来越大,模块越来越多,模块设计者对模块的管理和维护越来越复杂,因此我们可以使用包来扩展模块的功能.

如何使用包

模块与包

导入模块发生的三件事:

  1. 创建一个模块的名称空间
  2. 执行.py文件,将执行过程中产生的名字存放在名称空间中
  3. 在当前执行文件中放入模块名,这个名字指向模块的名称空间

导入包发生的三件事情:

  1. 创建一个包的名称空间
  2. 由于包是一个文件夹,无法执行包,因此执行包下的.py文件,将执行过程中产生的名字存放在包名称空间中(即包的名称空间存放的名字都是来自.py)
  3. 在当前执行文件中放入包名,这个名字指向包的名称空间

包是含有_\_init__.py的文件夹; 导包就是导入__init__.py

包一定是被当作模块文件导入,模块文件 m1.py/m2.py 的搜索路径以执行文件 包的介绍.py 路径为准

导的哪个名称空间的名字就能使用这个名称空间,导的哪个函数名或者变量名就能使用这个函数或者变量

扩展模块功能

1569666437490

导入包内包

# aaaa/.py
from aaaa import bbb

导入包内包的模块

# bbb/.py
from aaaa.bbb import m3
# aaaa/.py
from aaaa.bbb.m3 import f1
# 包的介绍
import aaaa

aaaa.f1()

绝对导入和相对导入

绝对导入:

from .m1 import *
from .m2 import *

相对导入:

  • .代表当前被导入文件所在的文件夹
  • ..代表当前被导入文件所在的文件夹的上一级
  • ...代表当前被导入文件所在的文件夹的上一级的上一级

注意事项

  1. 包内所有的文件都是被导入使用的,而不是被直接运行的
  2. 包内部模块之间的导入可以使用绝对导入(以包的根目录为基准)与相对导入(以当前被导入的模块所在的目录为基准),推荐使用相对导入
  3. 当文件是执行文件时,无法在该文件内用相对导入的语法,只有在文件时被当作模块导入时,该文件内才能使用相对导入的语法
  4. 凡是在导入时带点的,点的左边都必须是一个包,import aaa.bbb.m3.f3错误

time模块

import time

print(time.time())  # 时间戳形式

time.sleep(1)  # 推迟指定的时间运行,单位为秒

datetime模块

# datetime可以看成是时间加减的模块
import datetime

# 返回当前时间
print(datetime.datetime.now())
2019-09-28 19:25:06.547227

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

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

# 当前时间+30分钟
print(datetime.datetime.now() + datetime.timedelta(minutes=30))
# 时间替换
print(now.replace(year=1949, month=10, day=1, hour=10, minute=1, second=0, microsecond=0))

random模块

import random

# 随机生成大于0且小于1的小数
print(random.random())
# 随机生成大于等于1小于3的整数
print(random.randint(1, 3))
# 随机生成大于1小于3的数
print(random.uniform(1, 3))
# 列表内的任意一个元素
print(random.choice([1, 2, 3]))
# random.sample([], n), 列表元素任意n个元素的组合(返回列表),示例n = 2
print(random.sample([1, 'a', ['b', 3], 2]))

[1, 'a']

# 打乱顺序,相当于洗牌
lis = [1, 2, 3, 4, 5]
random.shuffle(lis)
print(lis)

[2, 5, 1, 4, 3]

hashlib和hmac模块

hashlib模块

什么是hash

hash是一种算法(Python3.版本里使用hashlib模块代替了md5模块和sha模块,主要提供 SHA1、SHA224、SHA256、SHA384、SHA512、MD5 算法),该算法接受传入的内容,经过运算得到一串hash值。

hash值的特点:

  1. 只要传入的内容一样,得到的hash值一样,可用于非明文密码传输时密码校验
  2. 不能由hash值返解成内容,即可以保证非明文密码的安全性
  3. 只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的,可以用于对文本的哈希处理

hash算法其实可以看成如下图所示的一座工厂,工厂接收你送来的原材料,经过加工返回的产品就是hash值

import hashlib

m = hashlib.md5()

m.update('tiny', encoding='utf8')
d60cadf1a41c651e1f0ade50136bad43

hmac模块

为了防止密码被撞库,我们可以使用python中的另一个hmac 模块,它内部对我们创建key和内容做过某种处理后再加密。

如果要保证hmac模块最终结果一致,必须保证:

  1. hmac.new括号内指定的初始key一样
  2. 无论update多少次,校验的内容累加到一起是一样的内容
import hmac

h1 = hmac.new(b'hash')
h1.update(b'so')
h1.update(b'hard')
print(h1.hexdigest())
4c463da92cbb01719a2167df41659dfb
h2 = hmac.new(b'hash')
h2.update(b'sohard')
print(h2.hexdigest())
4c463da92cbb01719a2167df41659dfb
h3 = hmac.new(b'hashsohard')
print(h3.hexdigest())
28263fbde1a5877e0d30f70afa079c06

typing模块

typing模块:与函数联用,控制函数参数的数据类型,提供了基础数据类型之外的数据类型

lt = [1, 2, 3, 4]
print(type(lt) is list)

from typing import Iterable, Iterator, Generator


# print(lt == Iterable) # False

def func(x: int, lt: Iterable) -> list:
    return [1, 2, 3]


func(10, '123123')

requests模块

requests模块:爬虫--》爬数据,模拟浏览器对url发送请求,拿到数据

import requests

url = 'www.baidu.com'

response = requests.get(url)
data = response.text
print(data)

re模块

正则re:从大的字符串中挑选出 具有某种形状特点的字符串

元字符

# 元字符

s = 'abcdabc'
#    abc
#        abc
#     bc  bc

# ^:以...开头
res = re.findall('^ab', s)
print(res)
res = re.findall('^bc', s)
print(res)
# $: 以..结尾
s = 'abcdabc'
res = re.findall('bc$', s)
print(res)

# .: 任意字符
s = 'abc红abc'
res = re.findall('abc.', s)
print(res)

# \d: 数字
s = 'skld2342ljk'
res = re.findall('\d', s)
print(res)

# \w: 非空,数字字母下划线
s = 'skld_23 42ljk'
res = re.findall('\w', s)
print(res)

# \s:空,空格/\t/\n
s = 'skld_23 42ljk'
res = re.findall('\s', s)
print(res)

# \D: 非数字
s = 'skld2342ljk'
res = re.findall('\D', s)
print(res)

# \W: 空
s = 'skld_23 42ljk'
res = re.findall('\W', s)
print(res)

# \S:非空
s = 'skld_23 42ljk'
res = re.findall('\S', s)
print(res)

# +: 前面的一个字符至少1个
s = 'abcddddd abcd abc'
print(re.findall('abcd+', s))

# ?:前面的一个字符0-1个
s = 'abcddddd abcd abc'
print(re.findall('abcd?', s))

# *:前面的一个字符至少0个
s = 'abcdddddddddddddddddd abcd abc'
print(re.findall('abcd*', s))

# []: 中括号内的都可以
s = 'abc bbc cbc dbc'
print(re.findall('[abc]bc', s))

# [^]: 中括号的都不可以
s = 'abc bbc cbc dbc'
print(re.findall('[^abc]bc', s))

# |:或
s = 'abc bbc dbc'
print(re.findall('abc|bbc', s))

# {2}:前面的字符2个

s = 'abccabc abccc'
print(re.findall('abc{2}', s))

# {1,2}:前面的字符2个

s = 'abccabc abccc'
print(re.findall('abc{1,2}', s))

# 贪婪模式

# .(任意字符)*(0-无穷个)

s = 'abcdefgbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbg'
print(re.findall('a.*g', s))

# 非贪婪模式(*******)

# .(任意字符)*(0-无穷个)?(让他进入非贪婪模式)
s = 'abcdefgbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbg'
print(re.findall('a.*?g', s))

# bug
# .(任意字符)*(0-无穷个)?(让他进入非贪婪模式)
s = 'abcdefg'
print(re.findall('.*?', s))

# 了解:特殊构造


# a(?=\d) :a后面是数字,但是不要数字,不消耗字符串内容
s = 'a123 aaaa a234 abc'
#    a1    aa
#           aa
#            aa a2    ab
print(re.findall('a(?=\d)', s))
print(re.findall('a(?=\w)', s))

# 匹配邮箱:
s = '#@#@#@nickchen121@163.com$$$$////nick@qq.com$$#$#$[]]2287273393@162.com@$2423423lksdlfj#'
# \w(字母/数字/下划线)+(0-无穷个)@ \w(字母/数字/下划线)+(0-无穷个).com
print(re.findall('\w+@\w+.com', s))

# 函数


## compile
s = 'abcd abcddd abc'
# res = re.compile('abcd*')
email_pattern = re.compile('\w+@\w+.com')
phone_patter = re.compile('\d{13}')
print(re.findall(email_pattern, s))

print(re.findall('abcd*', s))

# ## match:  从开头找一个,找得到就不找了 ;找不到报错 --》
# s = 'ab abcddd abc'
# res = re.match('abcd*', s)
# print(res.group())

## search: 从字符串找一个,就不找了
s = 'ab abcddd abc'
res = re.search('abcd*', s)
print(res.group())

## split
s = 'ab23423abcddd234234abcasdfjlasjdk234l23lk4j2kl34kl25k3j2kl3j5lkj'
print(re.split('\d+', s))

## sub == replace
s = 'ab23423abcddd234234abcasdfjlasjdk234l23lk4j2kl34kl25k3j2kl3j5lkj'
print(re.sub('\d+', ' ', s))

## subn --> 替换了多少次
s = 'ab23423abcddd234234abcasdfjlasjdk234l23lk4j2kl34kl25k3j2kl3j5lkj'
print(re.subn('\d+', ' ', s))

# 补充(非常有用)

## 修饰符 --> re.S会让.匹配换行符(*****)
s = '''abc
abcabc*abc
'''

# .不匹配换行
print(re.findall('abc.abc', s))  # ['abc*abc']
print(re.findall('abc.abc', s, re.S))  # ['abc\nabc', 'abc*abc']

## 分组 --> 只要括号里的(*****)
s = 'abc abcd abcdd'
print(re.findall('a(.)c(d)', s))

## 有名分组(了解)
s = 'abc abcd abcdd'
print(re.search('a(?P<name>.)c(?P<name2>d)', s).groupdict())

# 超高级用法
s = 'abc123abc123'  # c123a
print(re.sub('c(\d+)a', ' ', s))
print(re.sub('c(?P<name1>\d+)a', ' \g<name1> ', s))  # \g<name1>这个东西不能替换掉

# 以下必须得记住

# .*?
# 贪婪和非贪婪
# findall
# re.S
# match和sarch的区别
# 分组
# 有名分组:给分组加名字


# 哪些做了解

# 杂七杂八的元字符
# 特殊构造元字符
# 特殊修饰符
posted @ 2019-09-28 21:26  二二二二白、  阅读(104)  评论(0编辑  收藏  举报