-day15--内置模块与开发规范

2023-11-15

day15 内置模块和开发规范

目标:掌握常见的内置模块的使用及了解软件开发的规范。

今日概要:

  • 内置模块
    • json
    • time
    • datetime
    • re
  • 开发规范
    • 主文件
    • 配置文件
    • 数据
    • 附件
    • 业务代码

1. 内置模块

1.1 json

json模块,是python内部的一个模块,可以将python的数据格式 转换为json格式的数据,也可以将json格式的数据转换为python的数据格式。

json格式,是一个数据格式(本质上就是个字符串,常用语网络数据传输)

# Python中的数据类型的格式
data = [
    {"id": 1, "name": "刘德华", "age": 18},
    {"id": 2, "name": "geek", "age": 18},
    ('egon',123),
]

# JSON格式
value = '[{"id": 1, "name": "刘德华", "age": 18}, {"id": 2, "name": "geek", "age": 18},["egon",123]]'
1.1.1 核心功能

json格式的作用?

跨语言数据传输,例如:
	A系统用Python开发,有列表类型和字典类型等。
	B系统用Java开发,有数组、map等的类型。

	语言不同,基础数据类型格式都不同。
	
	为了方便数据传输,大家约定一个格式:json格式,每种语言都是将自己数据类型转换为json格式,也可以将json格式的数据转换为自己的数据类型。

Python数据类型与json格式的相互转换:

  • 数据类型 -> json ,一般称为:序列化

    import json
    
    data = [
        {"id": 1, "name": "刘德华", "age": 18},
        {"id": 2, "name": "geek", "age": 18},
    ]
    
    res = json.dumps(data)
    print(res) # '[{"id": 1, "name": "\u5218\u5fb7\u534e", "age": 18}, {"id": 2, "name": "geek", "age": 18}]'
    
    res = json.dumps(data, ensure_ascii=False)
    print(res) # '[{"id": 1, "name": "刘德华", "age": 18}, {"id": 2, "name": "geek", "age": 18}]'
    
  • json格式 -> 数据类型,一般称为:反序列化

    import json
    
    data_string = '[{"id": 1, "name": "刘德华", "age": 18}, {"id": 2, "name": "geek", "age": 18}]'
    
    data_list = json.loads(data_string)
    
    print(data_list)
    
练习题
  1. 写网站,给用户返回json格式数据

    • 安装flask模块,协助我们快速写网站(之前已安装过)

      pip3 install flask
      
    • 使用flask写网站

      import json
      from flask import Flask
      
      app = Flask(__name__)
      
      
      def index():
          return "首页"
      
      
      def users():
          data = [
              {"id": 1, "name": "刘德华", "age": 18},
              {"id": 2, "name": "geek", "age": 18},
          ]
          return json.dumps(data)
      
      
      app.add_url_rule('/index/', view_func=index, endpoint='index')
      app.add_url_rule('/users/', view_func=users, endpoint='users')
      
      if __name__ == '__main__':
          app.run()
      
  2. 发送网络请求,获取json格式数据并处理。

    import json
    import requests
    
    url = "https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=5&page_start=20"
    
    res = requests.get(
        url=url,
        headers={
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
        }
    )
    
    # json格式
    print(res.text)
    
    # json格式转换为python数据类型
    data_dict = json.loads(res.text)
    print(data_dict)
    
1.1.2 类型要求

python的数据类型转换为 json 格式,对数据类型是有要求的,默认只支持:

    +-------------------+---------------+
    | Python            | JSON          |
    +===================+===============+
    | dict              | object        |
    +-------------------+---------------+
    | list, tuple       | array         |
    +-------------------+---------------+
    | str               | string        |
    +-------------------+---------------+
    | int, float        | number        |
    +-------------------+---------------+
    | True              | true          |
    +-------------------+---------------+
    | False             | false         |
    +-------------------+---------------+
    | None              | null          |
    +-------------------+---------------+
data = [
    {"id": 1, "name": "刘德华", "age": 18},
    {"id": 2, "name": "geek", "age": 18},
]

其他类型如果想要支持,需要自定义JSONEncoder才能实现【目前只需要了解大概意思即可,以后项目开发中用到了还会讲解。】,例如:

import json
from decimal import Decimal
from datetime import datetime

data = [
    {"id": 1, "name": "刘德华", "age": 18, 'size': Decimal("18.99"), 'ctime': datetime.now()},
    {"id": 2, "name": "geek", "age": 18, 'size': Decimal("9.99"), 'ctime': datetime.now()},
]


class MyJSONEncoder(json.JSONEncoder):
    def default(self, o):
        if type(o) == Decimal:
            return str(o)
        elif type(o) == datetime:
            return o.strftime("%Y-%M-%d")
        return super().default(o)


res = json.dumps(data, cls=MyJSONEncoder)
print(res)
1.1.3 其他功能

json模块中常用的是:

  • json.dumps,序列化生成一个字符串。

  • json.loads,发序列化生成python数据类型。

  • json.dump,将数据序列化并写入文件(不常用)

    import json
    
    data = [
        {"id": 1, "name": "刘德华", "age": 18},
        {"id": 2, "name": "geek", "age": 18},
    ]
    
    file_object = open('xxx.json', mode='w', encoding='utf-8')
    
    json.dump(data, file_object)
    
    file_object.close()
    
  • json.load,读取文件中的数据并反序列化为python的数据类型(不常用)

    import json
    
    file_object = open('xxx.json', mode='r', encoding='utf-8')
    
    data = json.load(file_object)
    print(data)
    
    file_object.close()
    

1.2 时间处理

  • UTC/GMT:世界时间

  • 本地时间:本地时区的时间。

Python中关于时间处理的模块有两个,分别是time和datetime。

1.2.1 time
import time

# 获取当前时间戳(自1970-1-1 00:00)
v1 = time.time()
print(v1)

# 时区
v2 = time.timezone
print(v2/60/60)

# 停止n秒,再执行后续的代码。
time.sleep(5)
1.2.2 datetime

在平时开发过程中的时间一般是以为如下三种格式存在:

  • datetime

    from datetime import datetime, timezone, timedelta
    
    v1 = datetime.now()  # 当前本地时间
    print(v1)
    
    tz = timezone(timedelta(hours=7))  # 当前东7区时间
    v2 = datetime.now(tz)
    print(v2)
    
    v3 = datetime.utcnow()  # 当前UTC时间
    print(v3)
    
    from datetime import datetime, timedelta
    
    v1 = datetime.now()
    print(v1)
    
    # 时间的加减
    v2 = v1 + timedelta(days=140, minutes=5)
    print(v2)
    
    # datetime类型 + timedelta类型
    
    from datetime import datetime, timezone, timedelta
    
    v1 = datetime.now()
    print(v1)
    
    v2 = datetime.utcnow()  # 当前UTC时间
    print(v2)
    
    # datetime之间相减,计算间隔时间(不能相加)
    data = v1 - v2
    print(data.days, data.seconds / 60 / 60, data.microseconds)
    
    # datetime类型 - datetime类型
    # datetime类型 比较 datetime类型
    
  • 字符串

    # 字符串格式的时间  ---> 转换为datetime格式时间
    text = "2021-11-11"
    v1 = datetime.strptime(text,'%Y-%m-%d') # %Y 年,%m,月份,%d,天。
    print(v1)
    
    # datetime格式 ----> 转换为字符串格式
    v1 = datetime.now()
    val = v1.strftime("%Y-%m-%d %H:%M:%S")
    print(val)
    
  • 时间戳

    # 时间戳格式 --> 转换为datetime格式
    ctime = time.time() # 11213245345.123
    v1 = datetime.fromtimestamp(ctime)
    print(v1)
    
    # datetime格式 ---> 转换为时间戳格式
    v1 = datetime.now()
    val = v1.timestamp()
    print(val)
    
  • 转换关系

    字符串  互相转换 datetime  互相转换  时间戳
    
    字符串通过 datetime 实现 与时间戳的互相转换
    

    在这里插入图片描述

练习题
  1. 日志记录,将用户输入的信息写入到文件,文件名格式为年-月-日-时-分.txt

    from datetime import datetime
    
    while True:
        text = input("请输入内容:")
        if text.upper() == "Q":
            break
            
        current_datetime = datetime.now().strftime("%Y-%m-%d-%H-%M")
        file_name = "{}.txt".format(current_datetime)
        
        with open(file_name, mode='a', encoding='utf-8') as file_object:
            file_object.write(text)
            file_object.flush()
    
  2. 用户注册,将用户信息写入Excel,其中包含:用户名、密码、注册时间 三列。

    import os
    import hashlib
    from datetime import datetime
    
    from openpyxl import load_workbook
    from openpyxl import workbook
    
    
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))
    FILE_NAME = "db.xlsx"
    
    
    def md5(origin):
        hash_object = hashlib.md5("sdfsdfsdfsd23sd".encode('utf-8'))
        hash_object.update(origin.encode('utf-8'))
        return hash_object.hexdigest()
    
    
    def register(username, password):
        db_file_path = os.path.join(BASE_DIR, FILE_NAME)
        if os.path.exists(db_file_path):
            wb = load_workbook(db_file_path)
            sheet = wb.worksheets[0]
            next_row_position = sheet.max_row + 1
        else:
            wb = workbook.Workbook()
            sheet = wb.worksheets[0]
            next_row_position = 1
    
        user = sheet.cell(next_row_position, 1)
        user.value = username
    
        pwd = sheet.cell(next_row_position, 2)
        pwd.value = md5(password)
    
        ctime = sheet.cell(next_row_position, 3)
        ctime.value = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    
        wb.save(db_file_path)
    
    
    def run():
        while True:
            username = input("请输入用户名:")
            if username.upper() == "Q":
                break
            password = input("请输入密码:")
            register(username, password)
    
    
    if __name__ == '__main__':
        run()
    
    

1.3 正则表达式相关

当给你一大堆文本信息,让你提取其中的指定数据时,可以使用正则来实现。例如:提取文本中的邮箱和手机号

import re

text = "楼主太牛了,在线想要 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可以15131255789,约起来呀"

phone_list = re.findall("1[3|5|8|9]\d{9}", text)
print(phone_list)
# 输出 ['15131255789']
1.3.1 正则表达式
1. 字符相关
  • egon 匹配文本中的egon

    import re
    
    text = "你好egon,你是个逗比egonasd"
    data_list = re.findall("egon", text)
    print(data_list) # ['egon', 'egon'] 
    
    # 可用于计算字符串中某个字符出现的次数
    re.findall("正则表达式", text)
    
  • [abc] 匹配a或b或c 字符。

    import re
    
    text = "dadksjadavbcc诗和远方指理想的生活csacba"
    data_list = re.findall("[abc]", text)
    print(data_list) # ['a', 'a', 'a', 'b', 'c', 'c', 'c', 'a', 'c', 'b', 'a']
    
    # [abc] 匹配a或b或c
    
    import re
    
    text = "dadksjadavbcc诗和远方qa指理想的生活csacbawffbbupqcceiqiff"
    data_list = re.findall("q[abc]", text)
    print(data_list) # ['qa', 'qc']
    
    # 匹配 qa,或者qb,或者qc
    
  • [^abc] 匹配除了abc以外的其他字符。

    import re
    
    text = "你好wffbbupff"
    data_list = re.findall("[^abc]", text)
    print(data_list)  # ['你', '好', 'w', 'f', 'f', 'u', 'p', 'f', 'f']
    
  • [a-z] 匹配a~z的任意字符( [0-9]也可以 )。

    import re
    
    text = "daverootrootadmin"
    data_list = re.findall("t[a-z]", text)
    print(data_list)  # ['tr', 'ta']
    
  • . 代指除换行符以外的任意字符。

    import re
    
    text = "daveraotroxotadmin"
    data_list = re.findall("r.o", text)
    print(data_list) # ['rao', 'roo']
    
    
    # 注意,并没有输出roxo,说明中间只能匹配一位
    text = "daveraoroxotadmin"
    data_list = re.findall("r.o", text)
    print(data_list) # ['rao']
    

    + 出现一次或者n次

    import re
    
    text = "daveraoroxotadmin"
    data_list = re.findall("r.+o", text) 
    print(data_list) # ['raoroxo']
    # 贪婪匹配,不管中间多少都能匹配到第一个r开头到最后一个o结尾,最长的匹配
    

    问号 匹配前一个字符0次或1次,前面的字符可有可无

    import re
    
    text = "daveraotrootadmin"
    data_list = re.findall("r.+?o", text)  # 非贪婪匹配,最短的匹配
    print(data_list) # ['rao', 'roo']
    
  • \w 代指字母或数字或下划线(汉字)。

    import re
    
    text = "北京海贼geek王北  京海贼geek王"
    data_list = re.findall("海\w+k", text)
    print(data_list) # ['海贼geek', '海贼geek']
    
    # \W 无法匹配到空格,所以输出:['海贼geek', '海贼geek']
    
    
    # 没空格则贪婪的匹配到最长
    text = "北京海贼geek王北京海贼geek王"
    data_list = re.findall("海\w+k", text)
    print(data_list) # ['海贼geek王北京海贼geek']
    
  • \d 代指数字

    import re
    
    text = "root-ad32min-add3-admd1in"
    data_list = re.findall("d\d", text)
    print(data_list) # ['d3', 'd3', 'd1']
    
    import re
    
    text = "root-ad32min-add3-admd1in"
    data_list = re.findall("d\d+", text)
    print(data_list) # ['d32', 'd3', 'd1']
    
  • \s 代指任意的空白符,包括空格、制表符等。

    import re
    
    text = "root admin add admin"
    data_list = re.findall("a\w+\s\w+", text)
    print(data_list) # ['admin add']
    # a 开头,\w 字母数字下划线, + 一个或多个字母数字下划线, \s 代表任意的空白符,空格,制表符
    
2. 数量相关
  • * 重复0次或更多次

    import re
    text = "abcabFFcabFFFc"
    data_list = re.findall("abF*c", text)
    print(data_list)
    # ['abc', 'abFFc', 'abFFFc'] # 去abF*c 不管F出现多少次都能取到
    
  • + 重复1次或更多次,至少一次

    import re
    
    text = "他是大傻个,确实是个大2傻,大3傻,大66666傻。"
    data_list = re.findall("大\d+傻", text)
    print(data_list) # ['大2傻', '大3傻', '大66666傻']
    
  • ? 重复0次或1次,+后面的?代表非贪婪匹配

    import re
    
    text = "他是大傻个,确实是个大2傻,大3傻,大66666傻。"
    data_list = re.findall("大\d?傻", text)
    print(data_list)  # ['大傻', '大2傻', '大3傻']
    
  • {n} 重复n次

    import re
    
    text = "a12345za567890"
    data_list = re.findall("a\d{5}", text)
    print(data_list)  # ['a12345', 'a56789']
    
    # {} 中的数字代表出现n次,\d代指数字,所有是a开头后加无个数字
    
  • {n,} 重复n次或更多次

    import re
    
    text = "a1234554321z---a56789012345"
    data_list = re.findall("a\d{7,}", text)
    print(data_list)  # ['a1234554321', 'a56789012345']
    
    #{n,} 代指出现次数大于等于n次都能匹配到
    
  • {n,m} 重复n到m次

    import re
    
    text = "a1234554321z---a5678901234055555"
    data_list = re.findall("a\d{10,11}", text)
    print(data_list) # ['a1234554321', 'a56789012340']
    # 第二个数取到了11位
    
    
    text = "a1234554321z---a5678901"
    data_list = re.findall("a\d{10,15}", text)
    print(data_list) # ['a1234554321']
    
3. 括号(分组)
  • 提取数据区域

    import re
    
    text = "楼主太厉害了,在线想要邮箱 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,约起来呀"
    data_list = re.findall("15131(2\d{5})", text)
    print(data_list)  # ['255789']
    
    # ()括号表示提前这个区域的内容
    
    import re
    
    text = "楼主太厉害了,在线想要邮箱 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,约起来呀"
    data_list = re.findall("15(13)1(2\d{5})", text)
    print(data_list)  # [ ('13', '255789')   ]
    
    # 多个括号
    
    import re
    
    text = "楼主太厉害了,在线想要邮箱 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,约起来呀15131266666"
    data_list = re.findall("15(13)1(2\d{5})", text)
    print(data_list)
    # [('13', '255789'), ('13', '266666')] 多次匹配,匹配成功放入元组中
    
    import re
    
    text = "楼主太厉害了,在线想要邮箱 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,约起来呀"
    data_list = re.findall("(15131(2\d{5}))", text)
    print(data_list)  # [('15131255789', '255789')]
    
    # 以外部大括号为整体,提取整体的一部分数据
    
  • 获取指定区域 + 或条件

    import re
    
    text = "楼主15131root太牛15131dave叉了,在线想要 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,约起来呀"
    data_list = re.findall("15131(2\d{5}|r\w+太)", text)
    print(data_list)  # ['root太', '255789'] 
    
    # “|” 或的意思,嵌套括号只提取括号中的部分内容
    
    import re
    
    text = "楼主15131root太牛15131dave了,在线想要 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,约起来呀"
    data_list = re.findall("(15131(2\d{5}|r\w+太))", text)
    print(data_list)  # [('15131root太', 'root太'), ('15131255789', '255789')]
    
练习题
  1. 利用正则匹配QQ号码

    [1-9]\d{4,}
    
  2. 身份证号码

    import re
    
    text = "dsf130429191912015219k13042919591219521Xkk"
    data_list = re.findall("\d{17}[\dX]", text)
    print(data_list) # ['130429191912015219', '13042919591219521X']
    # 中括号只支持一个字符的或,多个需要使用分组,小括号
    
    import re
    
    text = "dsf130429191912015219k13042919591219521Xkk"
    data_list = re.findall("\d{17}(\d|X)", text)
    print(data_list) # ['9', 'X']
    
    import re
    
    text = "dsf130429191912015219k13042919591219521Xkk"
    data_list = re.findall("(\d{17}(\d|X))", text)
    print(data_list) # [('130429191912015219', '9'), ('13042919591219521X', 'X')]
    
    import re
    
    text = "dsf130429191912015219k13042919591219521Xkk"
    data_list = re.findall("(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)", text)
    print(data_list) # [('130429', '1919', '12', '01', '521', '9'), ('130429', '1959', '12', '19', '521', 'X')]
    
  3. 手机号

    import re
    
    text = "我的手机号是15133377892,你的手机号是1171123啊?"
    data_list = re.findall("1[3-9]\d{9}", text)
    print(data_list)  # ['15133377892']
    
  4. 邮箱地址

    import re
    
    text = "楼主太厉害了,在线想要邮箱 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,约起来呀"
    email_list = re.findall("\w+@\w+\.\w+",text)
    print(email_list) # ['442662578@qq.com和xxxxx']
    
    import re
    
    text = "楼主太厉害了,在线想要邮箱 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,约起来呀"
    email_list = re.findall("[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+", text, re.ASCII)
    print(email_list) # ['442662578@qq.com', 'xxxxx@live.com']
    
    # [a-zA-Z0-9_-] 可能是大小写字母,0-9, _ -
    # \. 反斜杠,转义符合,让点没有含义就是一个 .
    

    re.ASCII 匹配时自动忽略中文

    import re
    
    text = "楼主太厉害了,在线想要邮箱 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,约起来呀"
    email_list = re.findall("\w+@\w+\.\w+", text, re.ASCII)
    print(email_list) # ['442662578@qq.com', 'xxxxx@live.com']
    
    import re
    
    text = "楼主太牛44266-2578@qq.com了吧,在线想要 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,嗨起来呀"
    email_list = re.findall("(\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)", text, re.ASCII)
    print(email_list) # [('44266-2578@qq.com', '-2578', '', ''), ('xxxxx@live.com', '', '', '')]
    
    # + re.ASCII 自动忽略中文
    
  5. 补充代码,实现获取页面上的所有评论(已实现),并提取里面的邮箱。

    # 先安装两个模块
    pip3 install requests
    pip3 install beautifulsoup4
    
    import re
    import requests
    from bs4 import BeautifulSoup
    
    res = requests.get(
        url="https://www.douban.com/group/topic/79870081/",
        headers={
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36',
        }
    )
    bs_object = BeautifulSoup(res.text, "html.parser")
    comment_object_list = bs_object.find_all("p", attrs={"class": "reply-content"})
    for comment_object in comment_object_list:
        text = comment_object.text
        # print(text)
        # 请继续补充代码,提取text中的邮箱地址
        email_list = re.findall("\w+@\w+\.\w+", text, re.ASCII)
        if email_list:
            print(email_list)
    
4. 起始和结束

上述示例中都是去一段文本中提取数据,只要文本中存在即可。

但,如果要求用户输入的内容必须是指定的内容开头和结尾,比就需要用到如下两个字符。

  • ^ 开始
  • $ 结束
import re

text = "啊442662578@qq.com我靠"
email_list = re.findall("^\w+@\w+.\w+$", text, re.ASCII)
print(email_list) # []
import re

text = "442662578@qq.com"
email_list = re.findall("^\w+@\w+.\w+$", text, re.ASCII)
print(email_list) # ['442662578@qq.com']

这种一般用于对用户输入数据格式的校验比较多,例如:

import re

text = input("请输入邮箱:")
email = re.findall("^\w+@\w+.\w+$", text, re.ASCII)
if not email:
    print("邮箱格式错误")
else:
    print(email)
5. 特殊字符

由于正则表达式中 * . \ { } ( ) 等都具有特殊的含义,所以如果想要在正则中匹配这种指定的字符,需要转义,例如:

import re

text = "我是你{5}大爷"
data = re.findall("你{5}大爷", text)
print(data) # []
import re

text = "我是你{5}大爷"
data = re.findall("你\{5\}大爷", text)
print(data)
1.3.2 re模块

python中提供了re模块,可以处理正则表达式并对文本进行处理。

  • findall,获取匹配到的所有数据

    import re
    
    text = "dsf130429191912015219k13042919591219521Xkk"
    data_list = re.findall("(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)", text)
    print(data_list) # [('130429', '1919', '12', '01', '521', '9'), ('130429', '1959', '12', '19', '521', 'X')]
    
  • match,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None

    import re
    
    text = "大小逗2B最逗3B欢乐"
    data = re.match("逗\dB", text)
    print(data) # None
    
    import re
    
    text = "逗2B最逗3B欢乐"
    data = re.match("逗\dB", text)
    if data:
        content = data.group() # "逗2B"
        print(content)
    
  • search,浏览整个字符串去匹配第一个,未匹配成功返回None

    import re
    
    text = "大小逗2B最逗3B欢乐"
    data = re.search("逗\dB", text)
    if data:
        print(data.group())  # "逗2B"
    
  • sub,替换匹配成功的位置

    import re
    
    text = "逗2B最逗3B欢乐"
    data = re.sub("\dB", "沙雕", text)
    print(data) # 逗沙雕最逗沙雕欢乐
    
    # 从左至右匹配几个
    import re
    
    text = "逗2B最逗3B欢乐"
    data = re.sub("\dB", "沙雕", text, 1)
    print(data) # 逗沙雕最逗3B欢乐
    
  • split,根据匹配成功的位置分割

    import re
    
    text = "逗2B最逗3B欢乐"
    data = re.split("\dB", text)
    print(data) # ['逗', '最逗', '欢乐']
    
    import re
    
    text = "逗2B最逗3B欢乐"
    data = re.split("\dB", text, 1)
    print(data) # ['逗', '最逗3B欢乐']
    
  • finditer

    import re
    
    text = "逗2B最逗3B欢乐"
    data = re.finditer("\dB", text)
    # 在循环的过程中,没循环一次找一次,并不是一下全部输出到内存
    for item in data:
        print(item.group())
    
    #输出
    2B
    3B
    
    import re
    
    text = "逗2B最逗3B欢乐"
    data = re.finditer("(?P<xx>\dB)", text)  # 命名分组
    for item in data:
        print(item.groupdict())
    # 输出 
    {'xx': '2B'}
    {'xx': '3B'}
    
    # 正则:命名分组(分组)  (?P<名称>正则)
    import re
    
    text = "dsf130429191912015219k13042919591219521Xkk"
    data_list = re.finditer("\d{6}(?P<year>\d{4})(?P<month>\d{2})(?P<day>\d{2})\d{3}[\d|X]", text)
    for item in data_list:
        info_dict = item.groupdict()
        print(info_dict)
    

小结

到此,关于最常见的内置模块就全部讲完了(共11个),现阶段只需要掌握这些模块的使用即可,在后续的课程和练习题中也会涉及到一起其他内置模块。

  • os
  • shutil
  • sys
  • random
  • hashlib
  • configparser
  • xml
  • json
  • time
  • datetime
  • re
Python提供了大约200多个内置的标准模块,涵盖了Python运行时服务、文字模式匹配、操作系统接口、数学运算、对象永久保存、网络和Internet脚本和GUI构建等方面

2. 项目开发规范

现阶段,我们在开发一些程序时(终端运行),应该遵循一些结构的规范,让你的系统更加专业。

2.1 单文件应用

当基于python开发简单应用时(一个py文件就能搞定),需要注意如下几点。

"""
文件注释
"""

import re
import random

import requests
from openpyxl import load_workbook

DB = "XXX"


def do_something():
    """ 函数注释 """

    # TODO 待完成时,下一期实现xxx功能
    for i in range(10):
        pass


def run():
    """ 函数注释 """

    # 对功能代码进行注释
    text = input(">>>")
    print(text)


if __name__ == '__main__':
    run()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j6WLZ2pH-1635293933228)(images/image-20210105160728297.png)]

2.2 单可执行文件

新创建一个项目,假设名字叫 【crm】,可以创建如下文件和文件夹来存放代码和数据。

crm
├── app.py        文件,程序的主文件(尽量精简)
├── config.py     文件,配置文件(放相关配置信息,代码中读取配置信息,如果想要修改配置,即可以在此修改,不用再去代码中逐一修改了)
├── db            文件夹,存放数据
├── files         文件夹,存放文件
├── src           包,业务处理的代码
└── utils         包,公共功能

示例程序见附件:crm.zip

在这里插入图片描述

2.3 多可执行文件

新创建项目,假设名称叫【killer】,可以创建如下文件和文件夹来存放代码和数据。

killer
├── bin					文件夹,存放多个主文件(可运行)
│   ├── app1.py
│   └── app2.py
├── config              包,配置文件
│   ├── __init__.py
│   └── settings.py
├── db                  文件夹,存放数据
├── files               文件夹,存放文件
├── src                 包,业务代码
│   └── __init__.py
└── utils               包,公共功能
    └── __init__.py

在这里插入图片描述

示例程序见附件:killer.zip

总结

  1. json格式和json模块
  2. json模块处理特殊的数据类型
  3. datetime格式与字符串、时间戳以及相关之间的转换。
  4. datetime格式时间与timedelta的加减。
  5. 两个datetime相减可以计算时间间隔,得到的是一个timedelta格式的时间。
  6. 了解正则表达式的编写方式和python中re模块的使用。
  7. 项目开发规范。

作业:开发短视频资讯平台

  • 有video.csv视频库文件,其中有999条短视频数据,格式如下:【 video.csv 文件已为大家提供好,在day15课件目录下。 】

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WW7WEkDy-1635293933233)(images/image-20210105223331765.png)]

  • 项目的核心功能有:

    • 分页看新闻(每页显示10条),提示用户输入页码,根据页码显示指定页面的数据。

      • 提示用户输入页码,根据页码显示指定页面的数据。
      • 当用户输入的页码不存在时,默认显示第1页
    • 搜索专区

      • 用户输入关键字,根据关键词筛选出所有匹配成功的短视频资讯。
      • 支持的搜索两种搜索格式:
        • id=1715025,筛选出id等于1715025的视频(video.csv的第一列)。
        • key=文本,模糊搜索,筛选包含关键字的所有新闻(video.csv的第二列)。
    • 下载专区

      • 用户输入视频id,根据id找到对应的mp4视频下载地址,然后下载视频到项目的files目录。

        • 视频的文件名为:视频id-年-月-日-时-分-秒.mp4

        • 视频下载代码示例

          import requests
          
          res = requests.get(
              url='https://video.pearvideo.com/mp4/adshort/20210105/cont-1715046-15562045_adpkg-ad_hd.mp4'
          )
          
          # 视频总大小(字节)
          file_size = int(res.headers['Content-Length'])
          
          download_size = 0
          with open('xxx.mp4', mode='wb') as file_object:
              # 分块读取下载的视频文件(最多一次读128字节),并逐一写入到文件中。 len(chunk)表示实际读取到每块的视频文件大小。
              for chunk in res.iter_content(128):
                  download_size += len(chunk)
                  file_object.write(chunk)
                  file_object.flush()
                  message = "视频总大小为:{}字节,已下载{}字节。".format(file_size, download_size)
                  print(message)
              file_object.close()
          
          res.close()
          
        • 下载的过程中,输出已下载的百分比,示例代码如下:

          import time
          
          print("正在下载中...")
          for i in range(101):
              text = "\r{}%".format(i)
              print(text, end="")
              time.sleep(0.2)
          
          print("\n下载完成")
          

附赠

自动采集梨视频1000条资讯的爬虫脚本。梨视频平台系统更新后可能会导致下载失败,到时候需根据平台调整再来修改代码。

"""
下载梨视频的:视频ID,视频标题,视频URL地址 并写入到本次 video.csv 文件中。

运行此脚本需要预先安装:
    pip install request
    pip install beautifulsoup4

"""
import requests
from bs4 import BeautifulSoup


def get_mp4_url(video_id):
    data = requests.get(
        url="https://www.pearvideo.com/videoStatus.jsp?contId={}".format(video_id),
        headers={
            "Referer": "https://www.pearvideo.com/video_{}".format(video_id),
        }
    )
    response = data.json()
    image_url = response['videoInfo']['video_image']
    video_url = response['videoInfo']['videos']['srcUrl']
    middle = image_url.rsplit('/', 1)[-1].rsplit('-', 1)[0]
    before, after = video_url.rsplit('/', 1)
    suffix = after.split('-', 1)[-1]
    url = "{}/{}-{}".format(before, middle, suffix)
    return url


def download_video():
    file_object = open('video.csv', mode='w', encoding='utf-8')
    count = 0
    while count <= 999:
        res = requests.get(
            url="https://www.pearvideo.com/category_loading.jsp?reqType=14&categoryId=&start={}".format(count)
        )
        bs = BeautifulSoup(res.text, 'lxml')
        a_list = bs.find_all("a", attrs={'class': "vervideo-lilink"})
        for tag in a_list:
            title = tag.find('div', attrs={'class': "vervideo-title"}).text.strip()
            video_id = tag.get('href').split('_')[-1]
            mp4_url = get_mp4_url(video_id)
            row = "{},{},{}\n".format(video_id, title, mp4_url)
            file_object.write(row)
            file_object.flush()
            count += 1
            message = "已下载{}个".format(count)
            print(message)
    file_object.close()


if __name__ == '__main__':
    download_video()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

-day15--内置模块与开发规范 的相关文章

  • 使用 Python 或 Django 处理收到的电子邮件?

    我了解如何通过 Django 发送电子邮件 但我希望用户能够回复电子邮件 如果他们发送 以及我收到 的电子邮件包含与某个字符串匹配的消息 我将调用一个函数 我已经做了一些谷歌搜索 但除了自己制作脚本之外似乎没有什么好的解决方案 如果有什么东
  • Python BS4 Scraper 仅返回每个页面的前 9 个结果

    我让这段代码按预期工作 只是它并没有完全按预期工作 一切似乎都很顺利 直到我检查了我的 csv 输出文件并注意到我每页只得到前 9 个结果 每页应该有 40 个结果 因此我得到的结果少于预期的 25 有什么想法吗 import reques
  • Django 是否使用一个线程来处理 WSGI 或 Gunicorn 中的多个请求?

    根据标题 我想知道 Django 在通过 WSGI 或 Gunicorn 运行时是否使用一个线程来处理多个请求 我知道从不应该访问的地方访问请求是一种不好的做法 但我仍然想这样做 我认为有充分的理由 例如在我的自定义模板加载器中访问当前用户
  • 如何在后台运行python程序以保持活动窗口相同

    我编写了一个程序 可以将前景窗口更改为显示器尺寸的 85 并且要成功运行 前景窗口需要保持不变 我已将 python 脚本 pyw 放入批处理文件 运行 pythonw 并在桌面上创建了批处理文件的快捷方式 并提供了快速运行它的快捷方式 我
  • Twython - 如何使用媒体 url 更新状态

    在我的应用程序中 我允许用户在 Twitter 上发帖 现在我想让他们通过媒体更新他们的状态 In twython py我看到一个方法update status with media从文件系统读取图像并上传到 Twitter 我的图像不在文
  • 根据两个预先计算的直方图报告两个样本的 K-S 统计量

    Problem 在这里 我绘制了存储在文本文件中的 2 个数据集 在列表中 dataset 每个包含 218 亿个数据点 这使得数据太大而无法作为数组保存在内存中 我仍然能够将它们绘制为直方图 但我不确定如何通过2 样本KS测试 http
  • SQLAlchemy+pymysql 错误:sqlalchemy.util.queue.Empty

    尝试使用 Eclispse 在 Ubuntu 上运行 Python 2 SQLAlchemy 0 8 和 MySQL5 2 但我不断收到以下错误 我使用 pymysql 实际上是 pymysql3 引擎 模块监视器 from sqlalch
  • Python Raspberry pi - 如果路径不存在,则跳过循环

    我有一个收集温度 文本文件中的值 的功能 它使用部分预定义的路径 但是 有时如果温度传感器未加载 断开连接 则路径不存在 如果路径不可用 如何设置条件或例外来跳过循环 我想使用 continue 但我不知道要设置什么条件 def read
  • 根据Python中两行之间的匹配创建一个带有[0,1]的新列

    我正在尝试将多个列表或数据帧与一个大型基础数据帧进行比较 然后对于任何匹配 我想附加一个存储 1 匹配或 0 不匹配的列 df pd DataFrame Name A B C D ID 5 6 6 7 8 9 7 list1 5 6 8 9
  • 使用 scikit 包在 Python 中绘制集群区域的边界

    这是我处理 3 个属性 x y 值 中的数据聚类的简单示例 每个样本代表其位置 x y 及其所属变量 我的代码发布在这里 x np arange 100 200 1 y np arange 100 200 1 value np random
  • Flask-Mail - 基于 Flask-Cookiecutter 异步发送电子邮件

    我的烧瓶项目基于烧瓶饼干切割机 https github com sloria cookiecutter flask我需要异步发送电子邮件 发送电子邮件的功能由以下配置米格尔的教程 https blog miguelgrinberg com
  • 如何在海龟图形中将多个按键绑定在一起?

    我正在尝试制作一个连接点的 python 游戏 我希望游戏记录 2 次按钮按下操作 示例 如果用户按向上和向右箭头键 乌龟将向东北方向移动 45 度 这是我的代码 import turtle flynn turtle Turtle win
  • 如何从分组数据创建直方图

    我正在尝试根据 pandas 中的分组数据创建直方图 到目前为止 我已经能够创建标准线图 但我不知道如何做同样的事情来获取直方图 条形图 我想获得泰坦尼克号事故中幸存者和未幸存者的 2 个年龄直方图 看看年龄分布是否存在差异 来源数据 ht
  • Keras ImageDataGenerator 相当于 csv 文件

    我在文件夹中排序了一堆数据 如下图所示 我需要构建一个 DataIterator 以便将数据放入神经网络模型中 当数据是图像时 我找到了很多例子来解决这个问题 使用 Keras 类图像数据生成器及其方法流自目录 但当数据是 csv 结构时则
  • 仅获取图像中的外部轮廓

    我有这段代码 可以在图像中绘制轮廓 但我只需要外部轮廓 import cv2 import numpy as np camino C Users Usuario Documents Deteccion de Objetos 123 jpg
  • 如何配置应用程序中的所有记录器

    Python 的日志记录模块允许模块或类定义自己的记录器 不同的记录器可以有不同的处理程序 其中一些可能选择记录到文件 而另一些则选择记录到标准输出 现在 我的应用程序使用其中几个模块 每个模块都有自己的记录器 这些记录器具有各种处理程序
  • 加载 IPython 笔记本时出错

    一旦我用 Jupyter 打开笔记本文件 它要求我转换文件 我就再也无法在标准 IPython 笔记本中打开它了 我收到以下错误 Error loading notebook Bad Request 2014 12 21 04 13 03
  • 将 celery 与 Flask 应用程序上下文一起使用会导致“弹出错误的应用程序上下文”。断言错误

    我或多或少使用设置来使用您的 Flask 应用程序上下文来运行 Celery 任务 http flask pocoo org docs 0 10 patterns celery http flask pocoo org docs 0 10
  • Python中矩阵元素的双重求和

    基于下面的简化示例 我想在我的代码中 from sympy import import numpy as np init printing x y symbols x y mat Matrix x 1 1 y X 1 2 3 Y 10 20
  • 重定向到破折号中的 url

    我正在使用 dash 构建一个仪表板 每当单击特定数据点时 我都会创建一个唯一的 url 如何将用户重定向到此创建的 url 我正在使用下面给出的代码 每当有人单击任何数据点时 单击事件就会触发并执行回调函数 app layout html

随机推荐

  • sql查找一列中某一数值出现次数大于2的记录

    sql查找一列中某一数值出现次数大于2的记录 百度知道
  • 机械臂控制——4

    Robot Drivers 机器人驱动程序可以控制连接到计算机的真实机器人 机器人驱动程序使用通用软件接口来控制和监视特定的机器人控制器 使计算机能够控制工业机器人 机器人驱动程序提供了脱机编程的替代方案 程序被模拟 生成 然后传输到机器人
  • python人工智能应用实例_90后博士说,从Python到人工智能只差这35个趣味案例,越学越有趣...

    有趣的生活每个人都向往 有趣的Python编程学习方式却不是每个人都体验过 以这35个趣味案例开始 让兴趣成为学习Python最好的动力 看看这35个趣味案例 几乎是每个案例都对应着一个Python的知识点 比如 以照猫画虎的案例 教你剖析
  • mysql中geometry类型的简单使用(搜索附近的人)

    mysql中geometry类型的简单使用 编写本文的目的 让和两天前的我一样的初学者 能够更快的使用geometry类型存储空间点数据 也是为了自己加深印象 更熟练的使用geometry类型 建表脚本 CREATE TABLE z gis
  • 微信小程序云开发教程一

    微信小程序云开发 初学者入门教程一 云开发环境搭建 本教程适合刚刚入门的小白 云开发为开发者提供完整的云端支持 弱化后端和运维概念 无需搭建服务器 使用平台提供的 API 进行核心业务开发 即可实现快速上线和迭代 同时这一能力 同开发者已经
  • Pandas数据分析初学--开始了解数据

    探索Chipotle快餐数据 作为一个Pandas初学者 今天用这道题目练手 分享出来 首先 impotr pandas as pd 1 将数据集存入一个名为chipo的数据框内 iris filename chipotle csv chi
  • SkyWalking链路追踪中Trace概念以及Trace与span的关系

    基本概念 在SkyWalking链路追踪中 Trace 追踪 是指一个请求或者一个操作从开始到结束的完整路径 它涵盖了分布式系统中所有相关组件的调用关系和性能信息 具体来说 Trace包含了一系列的span 跨度 每个span代表了一个组件
  • kibana使用_从kibana迁移到grafana作为elasticsearch的展现

    今天说说 我们为什么会选择从kibana迁移到grafana 并选用grafana作为elasticsearch的图表展现工具 文章中关于kinaba和grafana的对比会有些片面 勿喷 最一开始使用kibana ElasticSearc
  • java 正则表达式_a-z_0-9 validation,掌握Java-Bean Validation

    数据校验虽然简单 但是却是一个繁琐的事 我在无数的代码看到if判断参数 然后错了打日志抛异常 一片一片的这种代码 如果有点重复了 再弄出N个xxUtil来归纳代码 虽然这种做法可以达到效果 但是代码散乱 一个是编写麻烦 一个是不易阅读 Ja
  • Pyqt5设计打开电脑摄像头+拍照(转载)

    本片为利用Pyqt5设计一个可以打开摄像头进行拍照的Demo 我感觉以后可能会有用 记录一下 Demo运行视频 哈哈感觉很好玩 用到的模块安装 库 安装 作用 PyQt5 pip install PyQt5 界面设计 opencv pyth
  • [网络安全自学篇] 三十五.恶意代码攻击检测及恶意样本分析

    本文主要结合作者的 系统安全前沿 作业 论文及绿盟李东宏老师的博客 从产业界和学术界分别详细讲解恶意代码攻击溯源的相关知识 在学术界方面 用类似于综述来介绍攻击追踪溯源的不同方法 在产业界方面 主要参考李东宏老师从企业恶意样本分析的角度介绍
  • 单调递增队列(全过程图文实现 另附习题)

    什么是单调队列 有什么用 不妨用一个问题来说明单调队列的作用和操作 不断地向缓存数组里读入元素 也不时地去掉最老的元素 不定期的询问当前缓存数组里的最小的元素 最直接的方法 普通队列实现缓存数组 进队出队都是O 1 一次查询需要遍历当前队列
  • 手把手教你如何 远程控制另一台电脑 保姆教程

    现在win10可以实现两台电脑之间的远程控制 下面我就分享一下如何利用快速助手进行远程控制另一台电脑 每一步都有截图 实验环境 两台win10系统的电脑 一 打开电脑后 需要设置允许电脑进行远程控制 进入 控制面板 系统和安全 系统 远程控
  • python文件操作图形化——python实战项目:单词练习系统

    python 文件操作与图形化编程 目录 python 文件操作与图形化编程 文件基本操作 图形化界面tkinter 单词练习系统 文件基本操作 D Python example txt 文件路径 D Python 文件名 example
  • 并行计算出现 pickle.PicklingError

    from multiprocessing import Pool def my function x return x x if name main inputs 1 2 3 4 5 with Pool 2 as p results p m
  • Unity面试题

    Unity基础面试题 1 什么是协同程序 2 Unity3D中碰撞器和触发器的区别 3 物体发生碰撞的必要条件 4 ArrayList和list的区别 5 如何安全的在不同工程间迁移Asset 6 OnEnable Awake Start的
  • Dubbo高级应用-服务治理

    目录 1 dubbo admin 2 7 x版本安装部署 1 1 下载源码 1 2 部署访问 2 路由规则 2 1 Dubbo API配置 2 2 管理控制台配置 3 规则动态配置 3 1 应用粒度 3 2 服务粒度 4 服务降级 5 集群
  • 集成 CUDA 实现 GPU 加速 OpenCV 计算机视觉

    特点 详细概述了将 OpenCV 与 CUDA 集成以用于实际应用 理解GPU与CUDA编程 通过一些实际示例 探索使用GPU和CUDA的OpenCV加速 熟悉在 NVIDIA Jetson TX1 上部署 OpenCV 应用程序 介绍了
  • python 类装饰器和函数装饰器区别_Python各种类型装饰器详解说明

    装饰器说明 Python中的装饰器是一种可以装饰其它对象的工具 该工具本质上是一个可调用的对象 callable 所以装饰器一般可以由函数 类来实现 装饰器本身需要接受一个被装饰的对象作为参数 该参数通常为函数 方法 类等对象 装饰器需要返
  • -day15--内置模块与开发规范

    day15 内置模块和开发规范 目标 掌握常见的内置模块的使用及了解软件开发的规范 今日概要 内置模块 json time datetime re 开发规范 主文件 配置文件 数据 附件 业务代码 1 内置模块 1 1 json json模