一、上周作业
# 1.写一个程序,传入一个群号,把这个群里所有人的头像下载到本地,头像的名字
# 如果这个人有群备注,那么图片的名称就是名字.jpg,如果没有名称就取昵称
# 因为需要登录,所以需要cookie
# https://q4.qlogo.cn/g?b=qq&nk=857566034&s=140
1.分析
import requests import os #判断存在否,不存在创建文件夹 if not os.path.exists('qq_pics'): os.mkdir('qq_pics') os.chdir('qq_pics') max_count = 200 gc = '1078641913' group_member_url = 'https://qun.qq.com/cgi-bin/qun_mgr/search_group_members' size = 20#定义步长 brn = 2027956891#可变的 cookie = '' #群里面最多200人 #0,20;21:41;42:62;.... count = 0 for j in range(0,max_count+1,20): headers = { 'user-agent': 'Mozilla/5.0', 'cookie': 'uin=o0544487209; skey=@EaiQXzjCW; RK=5NQIdFmjOh; ptcz=bfdea3df51354dc33cd2968594175f2ac8e8c56e2fd70a6067b2e92f1e78cd86; p_uin=o0544487209; pt4_token=c9ZNSP*7XNRwG5UgwGdvMbkYsXywb21nwYaqwaD39Ds_; p_skey=S-ceAUF1J0euCGX5Dqne6uBfHAGJp-RJqG5OSxRoA98_; traceid=9da1ab4551' } data = { 'gc': gc,'st': j,'end': j+size+count,'sort': 0,'bkn': 2027956891} r = requests.post(group_member_url,data,headers=headers) members = r.json() count += 1 if 'mems' in members: pic_url ='https://q4.qlogo.cn/g?b=qq&nk=%s&s=140' #all_count = members.get('count') mems = members.get("mems") for m in mems: qq = m.get("uin") #如果card的值取到了,就取card,没有取到取nick,非空即真 name = m.get('card') if m.get('card') else m.get('nick') r = requests.get(pic_url %qq) with open(name+'.jpg','wb') as fw: fw.write(r.content) print('下载完成%s'%name) else: print('没有获取到群成员信息') break
2.登录并支付
# 2.写登录接口,登录成功之后返回seesionid:xxx
# 当前时间戳time.time()+username,做md5 生成sessionid,session过期时间,自己定义
# seesion会放到redis里面,
# redis里面存进入sessionid,fd:userid,time过期时间
# 2.2支付接口
# 建表table、存userid和money
# 1,20000
# /pay?sessionid=xxxx&money=90
#校验sessionid是否失效,取不到不是错的就是过期了,如果支付金额>余额数据库的就失败,<就成功扣钱
import time import flask import tools,json import uuid server = flask.Flask(__name__) #登录 @server.route('/login',methods=['post','get']) def login(): username = flask.request.values.get('username','') password = flask.request.values.get('password','') if username.strip() and password.strip(): #给密码加密 p = tools.my_md5(password) #从mysql获取是否存在 query_sql = 'select * from app_myuser where username= "%s" and passwd="%s";' % (username, p) user_result = tools.execute_sql(query_sql) if user_result: #生成sessionid,session是使用用户名+时间戳+uuid生成的 session_str = '%s%s%s'%(username,time.time(),uuid.uuid4()) #加密 session_id = tools.my_md5(session_str) #获取ID,name,存入redis中 user_id = user_result.get('id') #存入key.value,超时时间,注意写入方式 tools.redis_str(session_id, '{"user_id":%s,"username":"%s"}' % (user_id, username), 600) return json.dumps({'code': '0', 'msg': '登录成功','sessionid':session_id},ensure_ascii=False) else: return json.dumps({'code': '-1', 'msg': '输入的用户名/密码错误'}) else: return json.dumps({'code': '-1', 'msg': '不能为空'}) # print(uuid.uuid4()) #支付 @server.route('/pay',methods=['post','get']) def pay(): tools.logger.debug('进入支付接口') sessionid = flask.request.values.get('sessionid','') money = float(flask.request.values.get('money')) tools.logger.debug('请求参数:{}',flask.request.values) session = tools.check_session(sessionid) if session: user = json.loads(session) user_id = user.get('user_id') sql = 'select balance from app_myuser where id = %s;'%user_id tools.logger.debug('sql语句:{}',sql) balance = tools.execute_sql(sql).get('balance') if balance>=money: update_money = 'update app_myuser set balance = balance - %s where id = %s;' %(money,user_id) tools.execute_sql(update_money) return json.dumps({'code': 0, 'msg': '支付成功'},ensure_ascii=False) else: return json.dumps({'code': -1, 'msg': '余额不足'},ensure_ascii=False) else: return json.dumps({'code': 899, 'msg': '请登录!'},ensure_ascii=False) if __name__ == '__main__': server.run(host='127.0.0.1',port=8999,debug=True) #在网站上输入这个地址查询 #http://127.0.0.1:8999/login?username=niuhanyang2&password=1 #http://127.0.0.1:8999/pay?money=1&sessionid=bcaee6b6b1a2746f27b1dbc5488003f5
二、tools文件新增
import traceback,hashlib import pymysql import redis import xlwt from loguru import logger import sys logger.remove() # 清除它的默认设置设置 fmt = '[{time}][{level}][{file.path}:line:{line}:function_name:{function}] ||msg={message}' # level file function module time message logger.add(sys.stdout, level='INFO', format=fmt) # 咱们本地运行的时候,在控制台打印 # logger.add('wxl.log',level='DEBUG',format=fmt,encoding='utf-8',enqueue=True,rotation='1 s',retention='10 seconds')#写在日志文件里面 logger.add('wxl.log', level='DEBUG', format=fmt, encoding='utf-8', enqueue=True, rotation='1 day', retention='10 days') # 写在日志文件里面 MYSQL_INFO = { 'host':'118.24.3.40', 'user':'jxz', 'password':'123456', 'db':'jxz', 'charset':'utf8', 'autocommit':True } REDIS_INFO = { 'host':'118.24.3.40', 'password':'HK139bc&*', 'port':'6379', 'db':'4', 'decode_responses':True #自动返回字符串 } def execute_sql(sql,more=False): #连接数据库 conn = pymysql.connect(**MYSQL_INFO) #xx=xxx,xx=xx cur = conn.cursor(pymysql.cursors.DictCursor) # 游标 try: cur.execute(sql)#没有问题,执行这句 except: logger.error('sql错误,{}',traceback.format_exc()) # print('sql不正确')#不正确走这句 # traceback.print_exc() # else: # return cur.fetchall() #None [{}] else:#执行完try执行else中的 if more: return cur.fetchall() #None [{}] return cur.fetchone() #{'xx':'xx'} finally: conn.close() cur.close() class Tool: @staticmethod def write_excel(name,data): book = xlwt.Workbook() sheet = book.add_sheet('sheet1') # 获取表头,写表头 for index, key in enumerate(data[0]):#写表头 sheet.write(0, index, key) for row, item in enumerate(data, 1): #写数据 for col, value in enumerate(item.values()): sheet.write(row, col, value) book.save(name + '.xls') print('导出完成') # @staticmethod # def my_md5(s): # s = str(s) # s = s.encode() # m = hashlib.md5(s) # bytes,不可逆 # result = m.hexdigest() # return result def my_md5(s): s = str(s) s = s.encode() m = hashlib.md5(s) # bytes,不可逆 result = m.hexdigest() return result def redis_str(key,value=False,expire_time=None): r = redis.Redis(**REDIS_INFO) if value: r.set(key,value,expire_time) else: return r.get(key) def redis_hash(): pass #校验sessionid def check_session(session_id): result = redis_str(session_id) if result: return result return False
三、写日志
import logging #python自带的工具 import loguru #第三方的写日志 import sys,time from loguru import logger #debug #调试信息,最低的级别 #info #正常的提示信息 #waring #警告信息 #error #出错了 ,走不动 #50-100 #写日志是io操作,会影响内存,一般正式环境设置日志级别都是 #exception #程序出异常了 sql执行出错了 def fd(): logger.remove() #默认的设置清楚掉,debug #设置日志级别 #stdout程序的标准输出,操作系统print才能在屏幕中写东西 # level file function module time message fmt = '[{time}][{level}][{file.path}:line:{line}:function_name:{function}] ||msg={message}' logger.add(sys.stdout,level='INFO',format=fmt)#本地运行,在控制台打印 #写到日志文件中 #enqueue=True异步写日志:先把日志放到消息队列里面,在启动一个线程,慢慢写进去,可以提高性能 #rotation默认时间: #rotation可以设置大小,超过多大就产生一个新文件1 kb,500 m,1 g #rotation可以多长时间,1 day,1 hour #rotation几点创建新文件,00:00,1:00 #retention删除日志,当前的日志不会受影响 logger.add('fd.log',level='DEBUG',format = fmt,encoding='utf-8',enqueue=True,rotation='1 day',retention='10 days')#部署到服务器的时候写在日志文件中 #超过20kb就会创建一个新的文件,最新的都是在不带日期中的 # logger.add('demo1.log',rotation='500 MB') #文件过大就会重新生成一个文件 # logger.add('demo1.log', rotation='01:00') #每天1点创建新文件 # logger.add('demo1.log', rotation='2 week')# 2个星期文件时间过长就会创建新文件 # logger.add('demo1.log', retention='7 days')#一礼拜后会清空除了当前日志之前的日志, for i in range(20): time.sleep(1) logger.debug('程序开始运行了') logger.debug('开始连接mysql') logger.info('mysql配置xxxx') logger.warning('警告,磁盘空间即将不足') logger.error('程序出错了') # logger.exception('出错了')#使用exception会出现NoneType:None fd() #同步==高并发,所以使用异步写日志 def write_log(msg): with open('a.log','a',encodong='utf-8') as fw: fw.write(msg)
四、jsonpath操作
s= {"ec":0,"errcode":0,"em":"","cache":0,"adm_num":3,"levelname":None,"mems":[{"uin":511402865,"role":0,"g":0,"join_time":1589360442,"last_speak_time":1600570983,"lv":{"point":0,"level":1},"card":"","tags":"-1","flag":0,"nick":"u671du82b1u5915u62fe","qage":14,"rm":0},{"uin":475566024,"role":1,"g":0,"join_time":1589360443,"last_speak_time":1596195430,"lv":{"point":0,"level":1},"card":"","tags":"-1","flag":0,"nick":"CC","qage":15,"rm":1},{"uin":616745045,"role":1,"g":0,"join_time":1589360443,"last_speak_time":1589360443,"lv":{"point":0,"level":1},"card":"","tags":"-1","flag":0,"nick":"u5927u5e08u5144","qage":14,"rm":1},{"uin":1473732204,"role":1,"g":0,"join_time":1589360443,"last_speak_time":1596699591,"lv":{"point":0,"level":1},"card":"","tags":"-1","flag":0,"nick":"u5b89u5927u53d4","qage":10,"rm":1},{"uin":1930890111,"role":2,"g":-1,"join_time":1589360638,"last_speak_time":1589363741,"lv":{"point":0,"level":1},"card":"","tags":"-1","flag":0,"nick":"56","qage":9,"rm":1},{"uin":549313033,"role":2,"g":0,"join_time":1590131830,"last_speak_time":1597542612,"lv":{"point":0,"level":1},"card":"u767du5b87u9e4f","tags":"-1","flag":0,"nick":"u79e6u6b87","qage":12,"rm":1},{"uin":121654011,"role":2,"g":1,"join_time":1591326665,"last_speak_time":1597549705,"lv":{"point":0,"level":1},"card":"u8e6du8bfe-u66f9u4e3au7f8e","tags":"-1","flag":0,"nick":"u265dAimeeu00b7Toou2740","qage":14,"rm":1},{"uin":411732604,"role":2,"g":1,"join_time":1591326665,"last_speak_time":1591584091,"lv":{"point":0,"level":1},"card":"","tags":"-1","flag":0,"nick":"u4e09u53f6u8349u7684u624bu6307","qage":14,"rm":1},{"uin":690763103,"role":2,"g":1,"join_time":1591326665,"last_speak_time":1599960754,"lv":{"point":0,"level":1},"card":"u674eu9ad8u82f1","tags":"-1","flag":0,"nick":"u4e24u6b21u65b9u7684u65cbu5f8b","qage":12,"rm":1},{"uin":1522503760,"role":2,"g":0,"join_time":1591326665,"last_speak_time":1598146137,"lv":{"point":0,"level":1},"card":"u79b9u6881","tags":"-1","flag":0,"nick":"u79b9u6881","qage":9,"rm":1},{"uin":635763064,"role":2,"g":1,"join_time":1592997221,"last_speak_time":1600572109,"lv":{"point":0,"level":1},"card":"u970du7d2bu9633","tags":"-1","flag":0,"nick":"u6f02u6d41u6d77u5cb8","qage":13,"rm":1},{"uin":857566034,"role":2,"g":1,"join_time":1593329449,"last_speak_time":1600565621,"lv":{"point":0,"level":1},"card":"u4ee3u723d","tags":"-1","flag":0,"nick":"u767du7fbdu5f52u697c","qage":12,"rm":1},{"uin":347158400,"role":2,"g":0,"join_time":1593345739,"last_speak_time":1599385077,"lv":{"point":0,"level":1},"card":"u6731u6210","tags":"-1","flag":0,"nick":"u9ea6u514b.vod","qage":16,"rm":1},{"uin":704096641,"role":2,"g":1,"join_time":1594023174,"last_speak_time":1600572110,"lv":{"point":0,"level":1},"card":"u803fu5a1f","tags":"-1","flag":0,"nick":"704096641","qage":13,"rm":1},{"uin":978502577,"role":2,"g":1,"join_time":1594883618,"last_speak_time":1599992058,"lv":{"point":0,"level":1},"card":"u5f20u4e39u96ea","tags":"-1","flag":0,"nick":"u3000u3000Amouru256eu66aeu5ff5","qage":9,"rm":1},{"uin":799614279,"role":2,"g":0,"join_time":1594884719,"last_speak_time":1600565607,"lv":{"point":0,"level":1},"card":"u9c81u6d25u5065","tags":"-1","flag":0,"nick":"u4e28u5bd2u5c10u6708u309e","qage":13,"rm":1},{"uin":695254152,"role":2,"g":0,"join_time":1594886366,"last_speak_time":1600572106,"lv":{"point":0,"level":1},"card":"u738bu7965u9f99","tags":"-1","flag":0,"nick":"u8ffdu68a6u8d64u5b50u5fc3","qage":13,"rm":1},{"uin":251202767,"role":2,"g":1,"join_time":1594943472,"last_speak_time":1600572310,"lv":{"point":0,"level":1},"card":"u9ad8u96ef","tags":"-1","flag":0,"nick":"u7d2bu8272u7cbeu7075","qage":16,"rm":1},{"uin":120617143,"role":2,"g":1,"join_time":1595481073,"last_speak_time":1596951515,"lv":{"point":0,"level":1},"card":"u7b71","tags":"-1","flag":0,"nick":"u6668u98ceu5915u96e8","qage":18,"rm":1},{"uin":357084975,"role":2,"g":1,"join_time":1595817181,"last_speak_time":1600572106,"lv":{"point":0,"level":1},"card":"u674eu97e9u97e9","tags":"-1","flag":0,"nick":"u2581u2581u5e7bu68a6u541fu8ff7u60d1u4e0du4f4fu7684u5fc3","qage":8,"rm":1},{"uin":296915611,"role":2,"g":-1,"join_time":1595927320,"last_speak_time":1600572383,"lv":{"point":0,"level":1},"card":"u9b4fu5f3a","tags":"-1","flag":0,"nick":"u8defu4ebau7532@u63d0u4e0du8d77u52b2","qage":13,"rm":1}],"count":48,"svr_time":1600572532,"max_count":200,"search_count":48,"extmode":0} import jsonpath #返回max_count的值为200 print(jsonpath.jsonpath(s,'$.max_count'))#返回的都是list #返回第一个mems的昵称 print(jsonpath.jsonpath(s,'$.mems[0].nick')) #可以模糊匹配 print(jsonpath.jsonpath(s,'$..level'))#取到所有leveld的值 #返回search_count的值 print(jsonpath.jsonpath(s,'$.search_count'))
五、my_db
import pymysql from loguru import logger import traceback MYSQL_INFO = { 'host':'118.24.3.40', 'user':'jxz', 'password':'123456', 'db':'jxz', 'charset':'utf8', 'autocommit':True } class MySQL: def __init__(self,host,user,password,db,charset='utf8',autocommit=True): self.conn = pymysql.connect(user=user,host=host,password=password,db=db,charset=charset,autocommit=autocommit) self.cursor = self.conn.cursor() def __del__(self): self.__close() def execute(self,sql): try: self.cursor.execute(sql) except Exception: logger.error('sql执行出错,sql语句是{}',sql) logger.error(traceback.format_exc()) def fetchall(self,sql): self.execute(sql) return self.cursor.fetchall() def fetchone(self,sql): self.execute(sql) return self.cursor.fetchone() def bak_db(self): pass def __close(self): self.cursor.close() self.conn.close() if __name__ == '__main__': my = MySQL(**MYSQL_INFO) print(my.fetchall('select * from app_myuser;')) my.fetchone('select * from app_myuser where id=1;') my.fetchone('select * from app_myuser where id=1;') my.fetchone('select * from app_myuser where id=1;')
六、面向对象
#以前的#面向过程 ''' 1.4s店看车,付钱 2.保险公司 3.车管所,办理临时拍照 4.缴税 5.车管所、上牌、行驶证 调用a b c 函数 执行者 ''' #面向对象==化零为整 ''' 买车处-> #1.4s店看车,付钱 #2.保险公司 # 3.车管所,办理临时拍照 #4.缴税 #5.车管所、上牌、行驶证 调用car() 指挥者 ''' ''' 类:一个模板,一个模型 对象:根据模板造出来的具体的东西 实例:根据模板造出来的具体的东西 实例化:把模板做成具体东西的过程 构造函数:类在实例化的时候,自动执行的函数2.如果要使用这个类,必须要传一些参数的时候,参数写在构造函数里面 self,this:本类对象 析构函数:实例被销毁的时候会自动执行 私有:只能通过self调用,不能通过实例调用;只能在类里面用,不能在类外面用 def __close(self): 类方法:公共的方法,直接可以通过类名来调用 不需要实例化,通过实例也可以调用 类变量:定义在类里面的变量 实例方法:必须实例化的时候才可以调用,参数里有self 静态方法:和一个普通的方法没有任何区别,和类也没有什么关系,只是定义在类里面而已 属性方法:一个看起来像变量的方法 继承:父子关系 python中没有封装和多态 面向对象的三大类型:封装、继承、多态(java强类型,python弱类型) ''' #类名首字母大写,驼峰 #函数名、变量名:xx_xx,下划线 import time class PresonManger:#经典类 pass class Person2():#新式类 pass class Person3(object):#新式类 pass #================================= class Person:#类 #类变量 country = 'Chain' def __init__(self,name,sex,country='Chain'): # 构造函数:类在实例化的时候,自动执行的函数 #变量中只要加了self之后,变量在这个类中所有函数都可以用 print('self的内存地址', id(self)) self.name = name self.sex = sex self.__height = 200 self.country = country self.birthday = time.time() self.cry() # print('我是构造函数') def __del__(self): #最后执行析构函数 print('我是析构函数%s'% self.name) @property #不能有参数,必须有返回值 def age(self): return int(time.tiem() - self.birthday) def run(self): print('%s run...'% self.name) def fly(self): print('%s fly'% self.name) def cry(self): print('%s 呜呜呜'% self.name) def say(self):#实例方法 print('my name is %s,sex is %s '% (self.name,self.sex)) print('%s 斤' %self.__height) print('我的国籍式%s'%self.country) @classmethod#类方法 def putonghua(cls): print(cls.country) print('会说普通话') @staticmethod#静态方法 def suangua(): print('test') bm = Person('小黑','2.男')#实例化 print('self的内存地址',id(bm)) #bm 对象,实例 bm.run() bm.country = 'Janpan'#类变量 Person.country = 'Janpan'#类方法 Person.putonghua() Person.suangua() Person.age#调用属性方法 bm.suangua() bm.say() # print(bm.__height) #私有的不可以使用 benz = Person('小白','女')#实例化 print('self的内存地址',id(benz)) benz.fly() #相当于Person.fly(benz) benz.say() del bm print('abc/////////////')
七、继承:
class Lw: def driver(self): print('开车') def make_money(self): print('挣5000钱') class Xw(Lw): #重写1:直接全部重写 def driver(self): print('开飞机✈') #重写2:先调用之前的方法,然后在执行新增的方法 def make_money(self): super().make_money() print('再5000块钱') a = Xw() a.driver() a.make_money() #======多态======== class Car:#基类 def __init__(self,name): self.name = name def run(self): print('%s run...' %self.name) class Bmw(Car): def fly(self): print('fly...') class Benz(Car): def swim(self): print('swim...') class Audi(Car): def liting(self): print('liting...') def run(obj): obj.run() c1 = Bmw('宝马') c2 = Benz('奔驰') c3 = Audi('奥迪') run(c1) run(c2) run(c3) class E: def daka(self): pass class E1: def daka(self): print('8:30') class E2: def daka(self): print('9:30') class E3: def daka(self): print('10:30')
八、总结: