python学习07-7月7日

02正则表达式

03爬虫练习
04hashlib

05configparser

06logging

09序列化模块

10模块和包



#复习
import queue
q = queue.Queue()
q.put(1)
print(q)


from collections import deque
dq = deque()
dq.append(1)
dq.insert(0,2) # 处理速度较列表快速
print(dq)
print(dq[1])


#插入比较:deque > 10*list
# ['a','b','c','d','e']
# --> 'b' 'c' 之间插入一个'f' ,'d','e'也会移动
# 链表
# 【内容,next指针】
# ['a'->'b'->'c'->'d'->'e']
#断开 b和c  b->f f->c


#取值 d[i]: list > deque
#道理同上

#正则表达式
# 元字符 . \w \d \s \W \D \S ^ $ [] [^] () |
# 量词 ?+ * {n} {n.} {n.m}
# 贪婪匹配 量词? 惰性

import random

def rm(m,n):
    m = m*100
    y = 0
    l = []
    for i in range(n):
        print(m)
        d = random.randint(1,m-1)
        y = m - d
        m = y
        if(i!=n):l.append(d)
        if(i==n-1):
            print('yyy',y)
            l.append(y)
        print(l,sum(l))
    return random.sample(l,n)
print(rm(100,9))

02正则表达式

# -*- coding:utf-8 -*-
#贪婪匹配
#贪婪 后向前匹配
#非 向后匹配 每次判断



# . 是任意字符
# * 是取 0 至 无限长度
# ? 是非贪婪模式。
# 何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:
# .*?x
#
# 就是取前面任意长度的字符,直到一个x出现

import re
ret= re.match('\d','2b22abcd')
print(ret.group())
# 匹配正则开头的
#检查 string 的 开头 是否 有 字符 与 pattern 匹配。
#match( pattern, string [, flags])

#findall: 取所有,返回列表
#search: 取匹配第一个 返回对象
#match : 取以开始的第一个 返回对象

ret = re.split(',','a,b,c,d')
print(ret)

ret = re.split('\d','a1b23c3d4e5f')
print(ret)

ret = re.split('\d+','a1b23c3d4e5f')
print(ret)


ret = re.split('\||,| ','a|b,c,d f')
print(ret)

ret = re.sub('\d+','|','a1b23c3d4e5f')
print(ret)

ret = re.subn('\d+','|','a1b23c3d4e5f')
print(ret)

re.search('\d\*\d','1+2-3+4-30')
#\d\*\d 先编再进行匹配 --> 翻译成python解析器可识别的
#在进行匹配

#第一步:编译对象
obj = re.compile('\d{3}')
#第二部:执行方法
print(obj.search('abcd123eeee'))
print(obj.findall('abcd123eeee'))

#返回一个可迭代对象
ret = re.finditer('\d','a1b2c3d4')
print(ret)
print(next(ret))
for i in ret:
    print(i.group())

# findall
# search
# match
# split
# sub/subn
# compile
# finditer

#() 的优先显示
ret  = re.findall('www\.(.+)\.com','www.baidu.com')
print(ret)
#保留你分隔的值
ret  = re.split('(\d+)','e1a3a4y')
print(ret)



#1、匹配标签
ret  = re.search('<(\w+)>\w+</(\w+)>','<h1>hello</h1>')
print(ret.group(1))
print(ret.group(2))

#h1 != b1 也能匹配
ret  = re.search('<(\w+)>\w+</(\w+)>','<h1>hello</b1>')
print(ret.group(1))
print(ret.group(2))

#增加分组
ret  = re.search('<(?P<tag>\w+)>\w+</(?P=tag)>','<h1>hello</b1>')
#print(ret.group('tag_name'))
ret  = re.search('<(?P<tag>\w+)>\w+</(?P=tag)>','<h1>hello</h1>')
print('tag_name',ret.group('tag'))

#使用编号分组 \n

ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>")
#如果不给组起名字,也可以用\序号来找到对应的组,表示要找的内容和前面的组内容一致
#获取的匹配结果可以直接用group(序号)拿到对应的值
print(ret.group(1))
print(ret.group())
#

#2、匹配整数
ret=re.findall(r"\d+","1-2*(60+(-40.35/5)-(-4*3))")
print(ret) #['1', '2', '60', '40', '35', '5', '4', '3']

# 结果错误

#需要现将 小数去掉
ret=re.findall("\d+(?:\.\d+)?","1-2*(60+(-40.35/5)-(-4*3))")
#取消分组法
print(ret)

ret=re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")
#()优先显示,去掉空
print(ret) #['1', '-2', '60', '', '5', '-4', '3']
ret.remove("")


#4、爬虫练习
# flages 选择
# re.I(IGNORECASE)忽略大小写,括号内是完整的写法
# re.M(MULTILINE)多行模式,改变^和$的行为
# re.S(DOTALL)点可以匹配任意字符,包括换行符
# re.L(LOCALE)做本地化识别的匹配,表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境,不推荐使用
# re.U(UNICODE) 使用\w \W \s \S \d \D使用取决于unicode定义的字符属性。在python3中默认使用该flag
# re.X(VERBOSE)冗长模式,该模式下pattern字符串可以是多行的,忽略空白字符,并可以添加注释


#正则指引

 

03爬虫练习

# -*- coding:utf-8 -*-
import re
from urllib.request import urlopen

import ssl

def get_page(url):
    context = ssl._create_unverified_context()
    response = urlopen(url,context=context)
    return response.read().decode('utf-8')


def parse_page(s):

    rt  ='<em class="">(?P<id>\d+)</em>.*?' \
         '<span class="title">(?P<title>\w+)</span>.*?' \
         '<span class="rating_num" property="v:average">(?P<rating_num>.*?)</span>.*?' \
         '<span>(?P<comment_num>\d+)人评价</span>'

    com = re.compile(rt,flags=re.S)
    ret = com.finditer(s)
    for i in ret:
        #print(i.group('id'),i.group('title'),i.group('rating_num'),i.group('comment_num'))
        yield {
            "id": i.group("id"),
            "title": i.group("title"),
            "rating_num": i.group("rating_num"),
            "comment_num": i.group("comment_num"),
        }



def main(num):
    url='https://movie.douban.com/top250?start=%s&filter='%num
    response_html=get_page(url)
    ret = parse_page(response_html)
    print(ret)
    f = open("move_info7.txt", "a", encoding="utf8")

    for obj in ret:
        print(obj)
        data = str(obj)
        f.write(data + "\n")



if __name__ == '__main__':
    count=0
    for i in range(10):
        main(count)
        count+=25

 


04hashlib

# -*- coding:utf-8 -*-
#
import hashlib

hashlib.md5()    #32位16进制的字符串
hashlib.sha1()   #32位32进制的字符串
hashlib.sha256()
hashlib.sha3_512()

s = 'abcd1234'

md5_obj  = hashlib.md5()

md5_obj.update(s.encode('utf-8'))

p = md5_obj.hexdigest()

print(p)


s = 'abcd1234'
username = 'username'
md5_obj  = hashlib.md5(username.encode('utf-8'))

md5_obj.update(s.encode('utf-8'))

p = md5_obj.hexdigest()

print(p)

# 1)使用同一个算法 同一个字符串 结果是一样的
# 2)摘要工程不可逆
# 3)对于不同的计算结果总是不同的

#md5sum 校验文件一致性


# 登录秘文
# 校验文件一致性

def compare():
    with open(r'02正则表达式.py','rb') as f1,\
        open(r'02正则表达式_1.py','rb') as f2:
        c1 = f1.read()
        c2 = f2.read()
        md1 = hashlib.md5()
        md1.update(c1)
        md2 = hashlib.md5()
        md2.update(c2)
        return md1.hexdigest() == md2.hexdigest()


print(compare())


s = 'abc'
s1 = 'd1'
s2 = '234'

md5_obj  = hashlib.md5()

md5_obj.update(s.encode('utf-8'))
md5_obj.update(s1.encode('utf-8'))
md5_obj.update(s2.encode('utf-8'))

p = md5_obj.hexdigest()
print(p)
#与abcd1234 结果一致

import os
def get_md5(file,n=10240):
    with open(file,'rb') as f1:
        md = hashlib.md5()
        fz = os.path.getsize(file)
        while fz>0:
            md.update(f1.read(n))
            fz -= n

    return md.hexdigest()

def compare1(file1,file2):
    return get_md5(file1)==get_md5(file2)

print(compare1('02正则表达式_1.py','02正则表达式.py'))

 

05configparser

# -*- coding:utf-8 -*-
# [组名 section]
# key = value


import configparser


# key 将不区分大小写
config = configparser.ConfigParser()

config["DEFAULT"] = {'ServerAliveInterval': '45',
                      'Compression': 'yes',
                     'CompressionLevel': '9',
                     'ForwardX11':'yes',
                     'file_path':r'aaa.py'
                     }

config['bitbucket.org'] = {'User':'hg'}

config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'}

with open('config.ini', 'w') as configfile:

   config.write(configfile)



import configparser

config = configparser.ConfigParser()

#---------------------------查找文件内容,基于字典的形式

print(config.sections())        #  []

config.read('config.ini')

print(config.sections())        # 不显示DEFAULT  ['bitbucket.org', 'topsecret.server.com']

print('bytebong.com' in config) # False
print('bitbucket.org' in config) # True


print(config['bitbucket.org']["user"])  # hg

print(config['DEFAULT']['Compression']) #yes

print(config['topsecret.server.com']['ForwardX11'])  #no


print(config['bitbucket.org'])          #<Section: bitbucket.org>

for key in config['bitbucket.org']:     # 注意,有default会默认default的键
    print(key)
#局部组将打印有default全局组

print(config.options('bitbucket.org'))  # 同for循环,找到'bitbucket.org'下所有键

print(config.items('bitbucket.org'))    #找到'bitbucket.org'下所有键值对

print(config.get('bitbucket.org','compression')) # yes       get方法Section下的key对应的value


#增删改操作

import configparser

config = configparser.ConfigParser()

config.read('example.ini')

config.add_section('yuan')



config.remove_section('bitbucket.org')
config.remove_option('topsecret.server.com',"forwardx11")


config.set('topsecret.server.com','k1','11111')
config.set('yuan','k2','22222')

config.write(open('new2.ini', "w"))

 

06logging

# -*- coding:utf-8 -*-
#1、简单配置方式 1)中文乱码 2)不能同时屏幕和文件输出
#2、logger对象配置方式


# import logging
# logging.debug('debug message')   # 调试模式
# logging.info('info message')     # 基础正常信息
# logging.warning('warning message') # 警告信息
# logging.error('error message')     # 错误信息
# logging.critical('critical message') #危险的

import logging

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    filename='test.log',
                    filemode='a')

logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')


#默认不打印debug 和info


# logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
#
# filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
# filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
# format:指定handler使用的日志显示格式。
# datefmt:指定日期时间格式。
# level:设置rootlogger(后边会讲解具体概念)的日志级别
# stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
#
# format参数中可能用到的格式化串:
# %(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用户输出的消息

 

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

#创建一个logger对象
#创建一个屏幕管理对象
#创建一文件管理对象
#创建一个格式对象

import logging

logger = logging.getLogger()

# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('test.log',encoding='utf-8')
logger.setLevel(logging.DEBUG)
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()

formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh) #logger对象可以添加多个fh和ch对象
logger.addHandler(ch)

logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

 



09序列化模块

# -*- coding:utf-8 -*-
# json
# pickle
# shelve

# 序列化 ?
# 序列 ?有序的结构
# 列表是序列吗?元组 字符串?
# 序列化 ?
# 实例化、结构化、序列化

# 数据机构 <-正>/反<序列化-> 字符串




#为什么要序列化
#1、文件存储
#2、网络传输


ls = [1,2,3,4]
print(repr(str(ls)))

s = str(ls)
print(list(s))

print(repr(eval(s)))


#----eval 问题
#1.对象传输
#2.安全隐患


import json

#dump

#load

#dumps 序列化 ->字符串

#load  反序列化->对象


#序列化 ->字符串
lst = [1,2,3,4,'aaa']
dic = {'a':1,'b':2,'c':3,'d':4}
print(lst)
print(dic)

ret1 = json.dumps(lst)
ret2 = json.dumps(dic)

print(ret1)
print(ret2)

# 单双引号区别
# [1, 2, 3, 4, 'aaa']
# {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# [1, 2, 3, 4, "aaa"]
# {"a": 1, "b": 2, "c": 3, "d": 4}

#反序列化->对象

res1 = json.loads(ret1)
res2 = json.loads(ret2)

print(res1)
print(res2)

#json 字典的key只能是字符串,并且只能是"引号
dic3 = {('a','b'):1}
# ret3 = json.dumps(dic3)
# res3 = json.loads(ret3)
# print(dic3,ret3,res3)
#抛出异常

#json 只支持有限的数据类型:字典,列表,数字类型
#元组会自动转换[]

import json

#---
# #dump # 只能跟文件相关
# f1 = open('tjson_file','w')
# json.dump([1,2,3],f1)
# f1.close()
# #load
#
# f2 = open('json_file','r')
# c = json.load(f2)
# f2.close()
# print(c,type(c))


# 需要连续dump 使用dumps
# 例如:10个字典
# 分别对每一个字典进行dumps


#编码--显示问题

import json
f = open('file','w')
#json.dump({'国籍':'中国'},f)
ret = json.dumps({'国籍':'中国'})
f.write(ret+'\n')
#json.dump({'国籍':'美国'},f,ensure_ascii=False)
ret = json.dumps({'国籍':'美国'},ensure_ascii=False)
f.write(ret+'\n')
f.close()


#格式化输出
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)
#指定 排序 缩紧 分隔符

#pickle
#支持所有数据类型,包括自定义类
#dump

#load

#dumps 序列化 ->字符串

#load  反序列化->对象
import pickle
class A:
    def __init__(self,name,age):
        self.name = name
        self.age = age

a = A('aaa',99)
f = open('pk_f','wb')
p  = pickle.dumps(a)
pp = pickle.dump(a,f)
print(p)
f.close()



l  = pickle.loads(p)
print(l.name)

f = open('pk_f','rb')
ll = pickle.load(f)
f.close()
print(ll.name)


ff = open('pk_f1','wb')
pickle.dump({1,2,3,4},ff)
pickle.dump({(1,2):456},ff)
ff.close()

ff1 = open('pk_f1','rb')
# print(pickle.load(ff1))
# print(pickle.load(ff1))
#多次DUMP
while True:
    try:
        print(pickle.load(ff1))
    except EOFError:
        break
ff1.close()


# json 结果可读,所有语言,数据类型有限
# pickle 结果bytes ,只python,几乎所有 (类必须存在)

#pickle -- 存档





##########shelve ###########

import shelve
f = shelve.open('shelve_file')
f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'}  #直接对文件句柄操作,就可以存入数据
f.close()

import shelve
f1 = shelve.open('shelve_file')
existing = f1['key']  #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(existing)
#这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB
#flag='r' 目前失效
# writeback=True

 

10模块和包

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

# bin -->
#       start.py 只管文件的启动
import os
import sys
print(sys.path)
Base_dir = os.path.dirname(os.path.dirname(__file__))
sys.path.append(Base_dir)
# from core import main
# main.entry_point

# conf -->
    # -> core -
    # -->
#       核心代码


# db -->
#      数据信息

# lib库文件
#       独立的功能

# log
# 日志文件

# 项目名最外层

 

posted @ 2018-07-11 16:43  在变老的小睿  阅读(185)  评论(0)    收藏  举报