subprocess、re、logging模块

一、subprocess模块

subprocess模块
- 可以通过python代码给操作系统终端发送命令,并且可以返回结果。

 1 import subprocess
 2 while True:
 3     # 让用户输入终端命令
 4     cmd_str = input('请输入终端命令:').strip()
 5     # Popen(cmd命令, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 6     # 调用Popen就会将用户的终端命令发送给本地操作系统的终端
 7     # 得到一个对象,对象中包含着正确或错误的结果。
 8     popen_obj = subprocess.Popen(
 9         cmd_str, shell=True,
10         stdout=subprocess.PIPE, stderr=subprocess.PIPE
11     )
12     success = popen_obj.stdout.read().decode('gbk')
13     if success:
14         print('正确命令!\n', success)
15     error = popen_obj.stderr.read().decode('gbk')
16     if error:
17         print('错误命令!\n', error)

 

二、re模块

re模块:
在python中,若想使用正则表达式,必须通过re模块来实现。

1、什么是正则表达式

- 正则表达式:
正则表达式是一门独立的技术, 任何语言都可以使用正则表达式,
正则表达式是由一堆特殊的字符组合而来的。
  - 字符组
  - 元字符
  - 组合使用

2、为什么要使用正则?

比如要获取“一堆字符串”中的“某些字符”,
正则表达式可以帮我们过滤,并提取出想要的字符数据。
# 比如过滤并获取 一段字符串中指定的字符串
- 应用场景:
- 爬虫: re, BeautifulSoup4, Xpath, selector
- 数据分析过滤数据: re, pandas, numpy...
- 用户名与密码、手机认证:检测输入内容的合法性

3、如何使用

检测手机号码的合法性, 需求: 11位、开头13/14/15/18

 1 # 纯python校验
 2 # 需求: 11位、开头13/14/15/18
 3 while True:
 4     phone_number = input('输入手机号:').strip()
 5     if phone_number.isdigit() and len(phone_number) == 11 and (
 6         phone_number.startswith('13') or
 7         phone_number.startswith('14') or
 8         phone_number.startswith('15') or
 9         phone_number.startswith('18')
10     ):
11         print('手机号码合格')
12     else:
13         print('手机号码不合格')
 1 # re效验
 2 import re
 3 while True:
 4     phone_number = input('输入手机号:').strip()
 5     # 需求: 11位、开头13/14/15/18
 6     # 参数1: 正则表达式  ''
 7     # 参数2: 需要过滤的字符串
 8     # ^: 代表“开头”
 9     # $: 代表“结束”
10     # |: 代表“或”
11     # (13|14): 可以获取一个值,判断是否是13或14.
12     # {1}: 需要获取1个值 限制数量
13     # []: 分组限制取值范围
14     # [0-9]: 限制只能获取0——9的某一个字符。
15     re_obj = re.match('^(13|14|15|18)[0-9]{9}', phone_number)
16     # print(re_obj)
17     if re_obj:
18         print('手机号码合格')
19     else:
20         print('手机号码不合格')
 1 """
 2 - 字符组:
 3   - [0-9] 可以匹配到一个0-9的字符
 4   - [9-0]: 报错, 必须从小到大
 5   - [a-z]: 从小写的a-z
 6   - [A-Z]: 从大写A-Z
 7   - [z-A]: 错误, 只能从小到大,根据ascii表来匹配大小。
 8   - [A-z]: 总大写的A到小写的z。
 9 
10   注意: 顺序必须要按照ASCII码数值的顺序编写。
11 """
12 import re
13 res = re.match('[A-Za-z0-9]{8}', 'yang1234')
14 print(res.group())
 1 """
 2 - 元字符:
 3     *******根据博客的表格来记 (看一眼)
 4     https://images2015.cnblogs.com/blog/1036857/201705/1036857-20170529203214461-666088398.png
 5 
 6     - 组合使用
 7       - \w\W: 匹配字母数字下划线与非字母数字下划线,匹配所有。
 8       - \d\D: 无论是数字或者非数字都可以匹配。
 9       - \t: table
10       - \n: 换行
11       - \b: 匹配单词结尾,tank  jasonk
12       - ^: startswith
13             - '^'在外面使用: 表示开头。
14             - [^]: 表示取反的意思。
15             
16       - $: endswith
17         
18       - ^$: 配合使用叫做精准匹配,如何限制一个字符串的长度或者内容。
19       - |: 或。ab|abc如果第一个条件成立,则abc不会执行,怎么解决,针对这种情况把长的写在前面就好了,一定要将长的放在前面。
20       - [^...]: 表示取反的意思。
21       - [^ab]: 代表只去ab以外的字符。
22       - [^a-z]: 取a-z以外的字符。
23 """

 

 

"""
re模块三种比较重要的方法:
    - findall(): ----> []
        可以匹配 "所有字符" ,拿到返回的结果,返回的结果是一个列表。
        'awfwaghowiahioawhio'  # a
        ['a', 'a', 'a', 'a']
        
    - search():----> obj ----> obj.group()
        'awfwaghowiahioawhio'  # a
        在匹配一个字符成功后,拿到结果后结束,不往后匹配。
        'a'
    
    - match():----> obj ----> obj.group()
        'awfwaghowiahioawhio'  # a
        'a'
        'wfwaghowiahioawhio'  # a
         None
        从匹配字符的开头匹配,若开头不是想要的内容,则返回None。
"""
 1 import re
 2 str1 = '1234 abcd 5678 efgh ==++'
 3 # findall
 4 # res = re.findall('[0-9]{4}', str1)
 5 # print(res)  # ['1234', '5678']
 6 
 7 # search
 8 # res = re.search('[0-9]{4}', str1)
 9 # print(res.group())  # 1234
10 
11 # match
12 res = re.match('[0-9]{4}', str1)
13 # print(res.group())
14 if res:
15     print(res.group())

4、爬虫应用

 1 """
 2 爬蟲四部原理:
 3     1.发送请求: requests
 4     2.获取响应数据: 对方机器直接返回的
 5     3.解析并提取想要的数据: re
 6     4.保存提取后的数据: with open()
 7 
 8 爬蟲三部曲:
 9     1.发送请求
10     2.解析数据
11     3.保存数据
12 """
13 
14 import requests
15 import re
16 
17 # 爬蟲三部曲:
18 # 1.发送请求
19 def get_page(url):
20     response = requests.get(url)
21     # response.content  # 获取二进制流数据,比如图片、视频、音频
22     # response.text  # 获取响应文本,比如html代码
23     return response
24 
25 # 2.解析数据
26 # 伪代码:
27 # response = get_page('url地址')
28 # parser_page(response.text)
29 def parser_page(text):      # response.text
30     # re.findall('正则表达式', '过滤的文本')
31     res_list = re.findall(
32         '<table width="100%" border="0".*?<a href="(.*?)" class="ulink">(.*?)</a>',
33         text,
34         re.S          # 全局匹配
35     )
36     for moive_tuple in res_list:
37         yield moive_tuple
38 
39 # 3.保存数据
40 # 伪代码:
41 # res_list = parser_page(text)
42 # save_data(res_list)
43 def save_data(res_list_iter):
44     with open('电影天堂.txt', 'a', encoding='utf-8')as f:
45         for movie_tuple in res_list_iter:
46             movie_url, name = movie_tuple
47             str1 = f"""
48             电影地址:{movie_url}
49             电影名字:{name}
50             """
51             f.write(str1)
52 
53 # 获取10个链接
54 n = 1
55 for line in range(10):
56     url = f'https://www.ygdy8.net/html/gndy/dyzz/list_23_{n}.html'
57     n += 1
58     print(url)
59 
60     response = get_page(url)
61     res_list_iter = parser_page(response.text)
62     save_data(res_list_iter)

三、logging模块

"""
logging模块的使用
   - 是用来记录日志的模块,一般记录用户在软件中的操作。
   def get_logger(user_type):
        # 1.加载log配置字典到logging模块的配置中
        logging.config.dictConfig(LOGGING_DIC)

        # 2.获取日志对象
        logger = logging.getLogger(user_type)
        return logger

   logger = get_logger('user')
   logger.info('日志消息')
"""
 1 import os
 2 import logging.config
 3 
 4 # 定义三种日志输出格式 开始
 5 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
 6                   '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
 7 
 8 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
 9 
10 id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
11 
12 # 定义日志输出格式 结束
13 # 注意1: log文件的目录
14 BASE_PATH = os.path.dirname(os.path.dirname(__file__))
15 logfile_dir = os.path.join(BASE_PATH, 'log_dir')
16 
17 # 注意2: log文件名
18 logfile_name = 'user.log'
19 
20 # 如果不存在定义的日志目录就创建一个
21 if not os.path.isdir(logfile_dir):
22     os.mkdir(logfile_dir)
23 
24 # log文件的全路径
25 logfile_path = os.path.join(logfile_dir, logfile_name)
26 
27 # 注意3: log配置字典,直接拿来用就可以了
28 LOGGING_DIC = {
29     'version': 1,
30     'disable_existing_loggers': False,
31     'formatters': {
32         'standard': {
33             'format': standard_format
34         },
35         'simple': {
36             'format': simple_format
37         },
38     },
39     'filters': {},
40     'handlers': {
41         #打印到终端的日志
42         'console': {
43             'level': 'DEBUG',
44             'class': 'logging.StreamHandler',  # 打印到屏幕
45             'formatter': 'simple'
46         },
47         # 打印到文件的日志,收集info及以上的日志
48         'default': {
49             'level': 'DEBUG',
50             'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
51             'formatter': 'standard',
52             'filename': logfile_path,  # 日志文件
53             'maxBytes': 1024*1024*5,  # 日志大小 5M
54             'backupCount': 5,
55             'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
56         },
57     },
58     'loggers': {
59         #logging.getLogger(__name__)拿到的logger配置
60         '': {
61             'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
62             'level': 'DEBUG',
63             'propagate': True,  # 向上(更高level的logger)传递
64         },
65     },
66 }
67 
68 # 注意4 使用模块
69 def get_logger(user_type):
70     # 1.加载log配置字典到logging模块的配置中
71     logging.config.dictConfig(LOGGING_DIC)
72 
73     # 2.获取日志对象
74     logger = logging.getLogger(user_type)
75     return logger
76 
77 logger = get_logger('yang')
78 logger.info('登录成功')

防止导入模块时自动执行测试功能
if __name__ == '__main__':
  执行测试模块

四、包

1.什么是包?
  包是一个带有__init__.py的文件夹,包也可以被导入,
  并且可以一并导入包下的所有模块。

2.为什么要使用包?
  包可以帮我们管理模块,在包中有一个__init__.py, 由它来帮我们管理模块。

3.怎么使用包?
  - import 包.模块名
  包.模块.名字

  - from 包 import 模块名

  - from 包.模块名 import 模块中的名字

- 导入包时发生的事情:
  1.当包被导入时,会以包中的__init__.py来产生一个名称空间。
  2.然后执行__init__.py文件, 会将__init__.py中的所有名字添加到名称空间中。
  3.接着会将包下所有的模块的名字加载到__init__.py产生的名称空间中。
  4.导入的模块指向的名称空间其实就是__init__.py产生的名称空间中。

 

posted @ 2019-11-19 17:54  treeter  阅读(162)  评论(0编辑  收藏  举报