五、python-jsonpath、写日志、面向对象

(一)jsonpath

 1、python需安装jsonpath模块

# 安装
pip install jsonpath

2、jsonpath使用

(1)模块导入使用:

# 模块提取方法
import json
from jsonpath import jsonpath

(2)语法规则

JSONPath Xpath 描述
$ / 根节点
@ . 过滤器断言(filter predicate)处理的当前节点对象,类似于this
.or[] / 取子节点
n/a ..

父元素,Jsonpath未支持

.. // 递归搜索,不管位置,选择所有符合条件的条件
* * 通配符,匹配所有的元素
n/a @ 属性访问字符,JsonPath不支持
[] [] 迭代器标示(可以在里面做简单的迭代操作,如数组下标,根据内容选值等)
[,] l 连接操作符在XPath结果合并其它节点集合。JsonPath允许name或者数组索引
?() [] 应用过滤表示式,可进行过滤操作
() n/a 脚本表达式,使用在脚本引擎下面,XPath不支持
[start:end:step] n/a 数组分割操作,XPath不支持
n/a () Xpath分组,JsonPath不支持

注意:

  • []在Xpath表达式总是从前面的路径来操作数组,索引是从1开始;
  • 使用JsonPath的[]操作符操作一个对象或者数组,索引是从0开始的。

(3)实例:https://qun.qq.com/cgi-bin/qun_mgr/search_group_members

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":1600967808,"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":0},{"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":0},{"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":0},{"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":0},{"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":0},{"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":0},{"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":0},{"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":0},{"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":0},{"uin":635763064,"role":2,"g":1,"join_time":1592997221,"last_speak_time":1600596210,"lv":{"point":0,"level":1},"card":"u970du7d2bu9633","tags":"-1","flag":0,"nick":"u6f02u6d41u6d77u5cb8","qage":13,"rm":0},{"uin":857566034,"role":2,"g":1,"join_time":1593329449,"last_speak_time":1600587021,"lv":{"point":0,"level":1},"card":"u4ee3u723d","tags":"-1","flag":0,"nick":"u767du7fbdu5f52u697c","qage":13,"rm":0},{"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":0},{"uin":704096641,"role":2,"g":1,"join_time":1594023174,"last_speak_time":1600588791,"lv":{"point":0,"level":1},"card":"u803fu5a1f","tags":"-1","flag":0,"nick":"704096641","qage":13,"rm":0},{"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":0},{"uin":799614279,"role":2,"g":0,"join_time":1594884719,"last_speak_time":1600575331,"lv":{"point":0,"level":1},"card":"u9c81u6d25u5065","tags":"-1","flag":0,"nick":"u4e28u5bd2u5c10u6708u309e","qage":13,"rm":0},{"uin":695254152,"role":2,"g":0,"join_time":1594886366,"last_speak_time":1600596152,"lv":{"point":0,"level":1},"card":"u738bu7965u9f99","tags":"-1","flag":0,"nick":"u8ffdu68a6u8d64u5b50u5fc3","qage":13,"rm":0},{"uin":251202767,"role":2,"g":1,"join_time":1594943472,"last_speak_time":1600596158,"lv":{"point":0,"level":1},"card":"u9ad8u96ef","tags":"-1","flag":0,"nick":"u7d2bu8272u7cbeu7075","qage":16,"rm":0},{"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":0},{"uin":357084975,"role":2,"g":1,"join_time":1595817181,"last_speak_time":1600596163,"lv":{"point":0,"level":1},"card":"u674eu97e9u97e9","tags":"-1","flag":0,"nick":"u2581u2581u5e7bu68a6u541fu8ff7u60d1u4e0du4f4fu7684u5fc3","qage":8,"rm":0},{"uin":296915611,"role":2,"g":-1,"join_time":1595927320,"last_speak_time":1600874827,"lv":{"point":0,"level":1},"card":"u9b4fu5f3a","tags":"-1","flag":0,"nick":"u8defu4ebau7532@u63d0u4e0du8d77u52b2","qage":13,"rm":0}],"count":48,"svr_time":1601129005,"max_count":200,"search_count":48,"extmode":0}

import jsonpath
# jsonpath取层级比较多,复杂的方式
print(jsonpath.jsonpath(s,'$.max_count'))
print(jsonpath.jsonpath(s,'$.mems[0]'))
print(jsonpath.jsonpath(s,'$.mems[0].nick'))
print(jsonpath.jsonpath(s,'$..level'))

执行结果如图:

(二)写日志:为了方便排查问题

1、Python自带的logging不是很好用,建议安装模块:loguru

# 安装loguru模块

pip install loguru

2、导入loguru模块 

# import logging  # python自带模块
# import loguru
from loguru import logger
# debug      打印日志比较详细,调试信息,最低的级别
# info       正常的提示信息
# warning    警告信息
# error      出错了
# exception  程序出异常了 SQL执行出错

import  sys
def Bob():
    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)  # print,输出,本地运行的时候,在控制台打印
    # logger.add('abc.log',level='INFO',encoding='utf-8',enqueue=True) # 写在日志文件里面
# enqueue=True ,异步写日志
logger.debug('程序开始运行了') logger.debug('开始连接MySQL') logger.info('MySQL配置XXXX') logger.warning('警告,磁盘空间即将不足!') logger.error('程序出错了!') Bob()

执行结果如图:

 3、定义写日志函数:

(1)同步写日志

# 同步写日志
def write_log(msg):
    with open('a.log','a',encoding='utf-8') as fw:
        fw.write(msg)

(2)异步写日志

from loguru import logger
import  sys
def Bob():
    logger.remove() # 清除以前它的默认设置
    fmt = '[{time}][{level}][{file.path}:{line}:function_name:{function}] || msg = {message}'  # level file function module time message
    logger.add(sys.stdout,level='INFO',format=fmt)  # print,输出 本地运行的时候,在控制台打印
    logger.add('abc.log',level='DEBUG',encoding='utf-8',enqueue=True,rotation='1 kb') # 写在日志文件里面

    # logger.add("demo1.log",rotation="500 MB") # 文件过大就会重新生成一个文件
    # logger.add("demo2.log",rotation="01:00")  # 每天1点创建新文件
    # logger.add("demo3.log",rotation="2 week") # 文件时间过长就会创建新文件
    # logger.add("demo4.log",retention="7 days") # 一个礼拜后会清空
    # enqueue=True,异步写日志
    
     for i in range(100):
        logger.debug('程序开始运行了')
        logger.debug('开始连接MySQL')
        logger.info('MySQL配置XXXX')
        logger.warning('警告,磁盘空间即将不足!')
        logger.error('程序出错了!')   

Bob()

(3)rotation和retention

  • rotation 可以设置大小,超过多大就产生一个新文件 1 kb,500 m,1 g
  • rotation 可以多长时间,1 day 1 hour
  • rotation 几点创建新文件,00:00 1:00
  • retention 多长时间清空日志

(三)面向对象

1、面向对象:定义类

(1)类(class)、类变量、数据成员、方法重写、局部变量、实例变量、对象、实例、实例化、继承、方法

   类:用来描述具有相同的属性和方法的对象的集合。对象是类的实例。一个模板,一个模型。例如:Class Car

  类变量:定义在类中且在函数体之外。类变量通常不作为实例变量使用。

  数据成员:类变量或者实例变量,用于处理类及其实例对象的相关的数据。

  方法:类中定义的函数。

  方法重写:从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称方法的重写。

  局部变量:定义在方法中的变量,只作用于当前实例的类。

  实例变量:在类的声明中,属性是用变量来表示的。这种变量就成为实例变量。

  对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。根据模板创造出来的具体的东西。例如:BMW为对象,实例

  实例:根据模板创造出来的具体的东西。例如:BMW=Car()实例化

  构造函数:

      A:类在实例化的时候,自动执行的函数

      B:如果要使用这个类,必须传一些参数写在构造函数里面

  实例化:创建一个类的实例,类的具体对象。把模板做成具体东西的过程  

  继承:一个派生类(derived class)继承基类(base class)的字段和方法。

# 1、经典类
class PersonManager:  
    pass

# 2、新式类
class Person2():
    pass

# 3、新式类
class Person3(object):
    pass

(2)实例,定义一个汽车类,且再定义方法

# 定义一个汽车类,并且定义方法
class Car:
    def run(self):
        print('run..')

    def baoyang(self):
        print('payfor')

BMW = Car()
BMW.run()
BMW.baoyang()

运行结果为:

(3)定义一个类:Person

class Person:
    def __init__(self,name,sex):
        # 构造函数,自动执行函数
        self.name = name
        self.sex = sex
        self.cry()
        print('我是构造函数')

    def eat(self):
        print('%s 在eating..' % self.name)

    def make(self):
        print('%s 在making..'% self.name)

    def say(self):
        print('my name is %s, sex is %s' %(self.name,self.sex))

    def cry(self):
        print('%s 哇哇哇哇'% self.name)

Nancy = Person('Nancy','Female')
Bob = Person('Bob','male')
Nancy.eat()
Bob.cry()

(4)基础重载方法

序号 方法,描述,简单的调用
1

_init_(self[,args...])

构造函数

简单的调用方法:obj = className(args)

2

_del_(self)

析构方法,删除一个对象

简单的调用方法:del obj

3

_repr_(self)

转化为供解释器读取的形式

简单的调用方法:repr(obj)

4

_str_(self)

用于将值转化为适于人阅读的形式

简单的调用方法:str(obj)

5

_cmp_(self,x)

对象比较

简单的调用方法:cmp(obj,x)

 (5)类的私有属性

  _private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。类内部的方法中使用时self._private_attrs。

(6)单下划线、双下划线、头尾双下划线说明:

  • _foo_:定义的是特殊方法,一般是系统定义名字,类似_init_()之类的
  • _foo:以单下划线开头的表示的是protected类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于from module import*
  • __foo:双下划线表示的是私有类型(private)的变量,只能是允许这个类本身进行访问了。

2、析构函数和构造函数,以及私有

实例:

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(host=host,user=user,password=password,db=db,charset=charset,autocommit=autocommit)
        self.cursor = self.conn.cursor()

    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)
    my.fetchall('select * from app_myuser;')
    my.fetchone('select * from app_myuser where id = 1;')
    my.execute('delete from user where id = 1;')
    my.close()

析构函数:实例被销毁的时候自动执行的函数。最后执行析构函数。

# 析构函数
class Person:
    def __init__(self,name,sex):
        # 构造函数
        self.name = name
        self.sex = sex
        self.cry()
        print('我是构造函数')

    def __del__(self):
        print('我是析构函数')

    def eat(self):
        print('%s 在eating..' % self.name)

    def make(self):
        print('%s 在making..'% self.name)

    def say(self):
        print('my name is %s, sex is %s' %(self.name,self.sex))

    def cry(self):
        print('%s 哇哇哇哇'% self.name)

Nancy = Person('Nancy','Female')
Bob = Person('Bob','male')
Nancy.eat()
Bob.cry()

私有:只能通过self调用,不能通过实例调用。

   只能在类里面用,类外面不能用。

   自己定义的方法和变量,如果是__开头,就是私有的

 3、各种方法类型

(1)类方法:公共的方法,直接可以通过类名来调用,不需要实例化,通过实例也可以调用(@classmethod)

    @classmethod
    # cls代表类方法
    def English(cls):
        print('会说英语!')

Person.English()

(2)类变量:定义在类里面的变量

class Person:
    country = 'China'
    def __init__(self,name,sex):
        self.name=name
        self.sex=sex

    def say(self):
        print('my name is %s, sex is %s' % (self.name, self.sex))
        print('我的国籍是 %s' % self.country)
Amy = Person('Amy','')
Amy.say()

执行结果为:

(3)实例变量(成员变量):self.XXX

class Person:
    country = 'China'
    def __init__(self,name,sex):
        self.name=name
        self.sex=sex

    def say(self):
        print('my name is %s, sex is %s' % (self.name, self.sex))
        print('我的国籍是 %s' % self.country)
Amy = Person('Amy','')
Bob = Person('Bob','')
Bob.country='UK'
Amy.say()
Bob.say()

执行结果为:

(4)静态方法(静态变量):和一个普通方法没有任何区别,和类也没有什么关系,只是定义在类里面(@staticmethod)

@staticmethod
    def test():
        print('小测试')

实例如下:

class Person:
    country = 'China'
    def __init__(self,name,sex):
        self.name=name
        self.sex=sex

    def say(self):
        print('my name is %s, sex is %s' % (self.name, self.sex))
        print('我的国籍是 %s' % self.country)

    @classmethod
    # cls代表类方法
    def English(cls):
        print('会说英语!')

    @staticmethod
    def test():
        print('小测试')
Person.test()
Person.English()
Amy = Person('Amy','')
Bob = Person('Bob','')
Bob.country='UK'
Amy.say()
Bob.say()
Bob.test()

执行结果如下:

 (5)属性方法:看起来像变量的方法,没有参数(@property)

import time
class Person:
    country = 'China'
    def __init__(self,name,sex):
        self.name=name
        self.sex=sex
        self.birthday=time.time()

    @property
    def age(self):
        return time.time() - self.birthday
Amy = Person('Amy','')
print(Amy.age)

(6)实例方法:必须通过实例化才可以调用,只要参数有self

4、面向对象的3大特性:封装、继承、多态

(1)封装:把零散的代码封装到一起,化零为整

(2)继承:用来节省代码

实例:

class Plant:
    def trees(self):
        print('这是一颗大树!')
    def origion(self):
        print('来着于云南省')
# yangshu继承Plant类
class yangshu(Plant):
    pass

a = yangshu()
a.trees()
a.origion()

执行结果如下:

(3)多态:Python里面根本不需要多态

(4)继承之重写:

A:重写-直接覆盖

class Plant:
    def trees(self):
        print('这是一颗大树!')
    def origion(self):
        print('来着于云南省')
# yangshu继承Plant类
class yangshu(Plant):
    # 重写
    def origion(self):
        print('来着于东北省')

a = yangshu()
a.trees()
a.origion()

执行结果为:

 

 B:重写-父用

class Plant:
    def trees(self):
        print('这是一颗大树!')
    def origion(self):
        print('来着于云南省')
# yangshu继承Plant类
class yangshu(Plant):
    # 重写-覆盖
    def origion(self):
        # super 找到父类,调用再定义
       super().origion()
       print('来着于北京市')

a = yangshu()
a.trees()
a.origion()

5、实例:

import os
import requests

max_count = 1000
size = 40
bkn = '2140990271'
cookies = 'pgv_pvi=328774656; RK=Bqzk3YEWb+; ptcz=4c3263932d8d5a48b929cd2283f1bde3146c1ee5c4f104796f0c8d95df45c3c8; tvfe_boss_uuid=7d887b37fe60ad85; pgv_pvid=3957380448; _qpsvr_localtk=0.9320463335905909; uin=o1270894070; skey=@78hV4b1qu; p_uin=o1270894070; pt4_token=taQ**Bbk0PIr3PB*-*yZeg*Fq8ENsjSXEeEf3Y-9m94_; p_skey=VJFMRPfcF8O-aOhbyYT*g0zfuIhUCzLdT175dWC8CzU_; traceid=f656b26bcb'
dir_name = 'qq_pics'

class DownLoadQQGroupMemberPic:
    group_member_url = 'https://qun.qq.com/cgi-bin/qun_mgr/search_group_members'
    pic_url = 'https://q4.qlogo.cn/g?b=qq&nk=%s&s=140'

    def __init__(self, gc):
        self.gc = gc
        self.mkdir()

    def mkdir(self):
        if not os.path.exists(self.dir_name):
            os.mkdir(self.dir_name)

    def get_member_info(self, gc, st, end):
        # 获取群成员的信息
        data = {'gc': gc, 'st': st, 'end': end, 'bkn': bkn}
        headers = {'cookie': cookies}
        r = requests.post(self.group_member_url, data, headers=headers)
        members = r.json
        return members

    def save_picture(self, name, content):
        with open(name + '.jpg', 'wb') as fw:
            fw.write(content)

    def download_picture(self, qq):
        r = requests.get(self.pic_url % qq)
        return r.content

    def down_qq_pic(self, mems):
        for m in mems:
            qq = m.get('uin')
            name = m.get('card') if m.get('card') else m.get('nick')
            content = self.download_picture(qq)
            self.save_picture(name, content)

    def main(self):
        count = 0
        for j in range(0, self.max_count + 1, self.size):
            mems = self.get_member_info(self.gc, j + count, j + self.size + count)
            if 'mems' in mems:
                self.down_qq_pic(mems)
温故而知新
原文地址:https://www.cnblogs.com/krystal-xiao/p/13724538.html