subprocess, re模塊,logging, 包等使用方法

subprocess, re模塊,logging, 包等使用方法

  • subprocess
'''
subprocess:
    sub: 子
    process: 進程
    能夠經過python代碼給操做系統終端發送命令,而且能夠返回結果
'''
import subprocess

while True:
    #一、讓用戶輸入終端命令
    cmd_str = input('請輸入終端命令:').strip()
    #Popen(cmd命令,shell=True,
    # stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    #調用Popen就會將用戶的終端命令傳給本地的操做系統終端
    #而且會獲得一個對象,對象中包含着正確或錯誤的結果
    obj = subprocess.Popen(cmd_str, shell=True,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)
    success = obj.stdout.read().decode('gbk')
    #中國windows的操做系統默認是中文,因此需轉成gbk
    if success:
        print(success, '正確的結果')

    error = obj.stderr.read().decode('gbk')
    if error:
        print(error, '錯誤的結果')
    '''
 請輸入終端命令:dir
 驅動器 D 中的卷是 新加捲
 卷的序列號是 38A2-829E

 D:\python的pycharm\正式課\day17 的目錄

2019/11/19  14:33    <DIR>          .
2019/11/19  14:33    <DIR>          ..
2019/11/19  14:33               947 subprocess模塊.py
2019/11/19  08:09               459 日考.py
               2 個文件          1,406 字節
               2 個目錄 132,886,355,968 可用字節
 正確的結果
 
 請輸入終端命令:yafeng
'yafeng' 不是內部或外部命令,也不是可運行的程序
或批處理文件。
    '''

  • re模塊
'''
奪命三問:
    一、什麼是正則表達式與re模塊?
        -正則表達式:
            -正則表達式是一門獨立的技術,任何;語言均可以使用正則表達式
            -正則表達式是由一堆特殊的字符組合而來
        -re模塊
            在python中,若想要使用正則表達式,必須經過re模塊使用
    二、爲何要使用正則?
        -好比要獲取'一堆字符串'中的'某些字符',正則表達式能夠幫咱們過濾,
        -並提取想要的字符串數據,好比從'afahafkfyafeng666'中獲取'yafeng666'

        -應用場景:
            -爬蟲:re,bs4,xpath,selector
            -數據分析過濾數據:re,pandas,numpy
            -用戶名與密碼手機認證:檢測輸入內容的合法性
    三、如何使用?
        -import re

- 字符組:
  - [0-9] 能夠匹配到一個0-9的字符
  - [9-0]: 報錯, 必須從小到大
  - [a-z]: 從小寫的a-z
  - [A-Z]: 從大寫A-Z
  - [z-A]: 錯誤, 只能從小到大,根據ascii表來匹配大小。
  - [A-z]: 總大寫的A到小寫的z。

  注意: 順序必需要按照ASCII碼數值的順序編寫。
'''

'''
- 元字符:
    *******根據博客的表格來記 (看一眼)
    https://images2015.cnblogs.com/blog/1036857/201705/1036857-20170529203214461-666088398.png

    - 組合使用
      - \w\W: 匹配字母數字下劃線與非字母數字下劃線,匹配全部。
      - \d\D: 不管是數字或者非數字均可以匹配。
      - \t: table
      - \n: 換行
      - \b: 匹配單詞結尾,tank  jasonk
      - ^: startswith
            - '^'在外面使用: 表示開頭。
            - [^]: 表示取反的意思。

      - $: endswith

      - ^$: 配合使用叫作精準匹配,如何限制一個字符串的長度或者內容。
      - |: 或。ab|abc若是第一個條件成立,則abc不會執行,怎麼解決,針對這種狀況把長的寫在前面就行了,必定要將長的放在前面。
      - [^...]: 表示取反的意思。
      - [^ab]: 表明只去ab之外的字符。
      - [^a-z]: 取a-z之外的字符。
'''

'''
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。
'''
![](https://img2018.cnblogs.com/blog/1843751/201911/1843751-20191119193657126-368101467.png)

![](https://img2018.cnblogs.com/blog/1843751/201911/1843751-20191119193714291-753474729.png)


#re校驗手機號碼的合法性
# 需求: 11位、開頭13/15/17開頭
# import re
# while True:
#     phone_number = input('請輸入您的號碼:').strip()
#     # 需求: 11位、開頭13/15/19
#     #     # 參數1: 正則表達式  ''
#     #     # 參數2: 須要過濾的字符串
#     #     # ^: 表明「開頭」
#     #     # $: 表明「結束」
#     #     # |: 表明「或」
#     #     # (13|14): 能夠獲取一個值,判斷是不是13或14.
#     #     # {9}: 須要獲取9個值 限制數量
#     #     # []: 分組限制取值範圍
#     #     # [0-9]: 限制只能獲取0——9的某一個字符。
#     if re.match('^(13)|(15)|(19)[0-9]{9}$', phone_number):
#         print('該號碼合法')
#         break
#     else:
#         print('該號碼不合法')
    #>>>請輸入您的號碼:13012345678
    #>>>該號碼合法
    #請輸入您的號碼:161234456789
    #>>>該號碼不合法

#match的用法
import re
str1 = 'abcdefgyafeng666'
res = re.match('[A-z0-9]', str1)
print(res)
#>>><re.Match object; span=(0, 1), match='a'>
print(res.group())   #只能獲取一個值
#>>>a


#findall的用法
res = re.findall('[a-z0-9]{7}', str1)
print(res)   #能夠獲取多個值
#>>>['abcdefg', 'yafeng6']


#search的用法

res = re.search('[a-y6-7]', str1)
print(res.group())   #只能獲取一個值
#>>>a
  • 利用re模塊爬取豆瓣電影
'''
爬取豆瓣TOP250電影信息

    第1頁:
        https://movie.douban.com/top250?start=0&filter=

    ...

    第9頁:
        https://movie.douban.com/top250?start=200&filter=

    第10頁:
        https://movie.douban.com/top250?start=225&filter=

爬蟲四部原理:
    1.發送請求: requests
    2.獲取響應數據: 對方機器直接返回的
    3.解析並提取想要的數據: re
    4.保存提取後的數據: with open()

爬蟲三部曲:
    1.發送請求
    2.解析數據
    3.保存數據


# 往10個連接發送請求獲取響應數據
    - requests模塊 ---》 請求庫
'''

import requests
import re


# 爬蟲三部曲
# 一、發送請求
def get_page(url):
    response = requests.get(url)
    # response.content#獲取二進制數據流,好比圖片,視頻
    # response.text#獲取響應文本,好比HTML代碼
    return response


# 僞代碼:
# response = get_page('url地址')
# parser_page(response.text)
# 二、解析數據
def parse_page(text):
    # re.findall('正則表達式', '過濾的文本')

    '''
    '<div class="item">.*?<a href="(.*?)">.*?<span class="title">(.*?)</span>.*?<span class="rating_num".*?>(.*?)</span>.*?<span>(.*?)人評價'

    :param text:
    :return:
    '''
    res_list = re.findall(
        '<div class="item">.*?<a href="(.*?)">.*?<span class="title">(.*?)</span>.*?<span class="rating_num".*?>(.*?)</span>.*?<span>(.*?)人評價'
        , text, re.S)  ## response.text


    for movie_tuple in res_list:
        yield movie_tuple




# 三、保存數據
# 僞代碼:
# res_list = parser_page(text)
# save_data(res_list)
def save_data(res_list_iter):
    with open('douban.txt', 'a', encoding='utf-8')as f:
        for movie_tuple in res_list_iter:
            movie_url, movie_name, movie_point, movie_num = movie_tuple
            # 寫入文件
            str1 = f'''
            電影地址:{movie_url}
            電影名字:{movie_name}
            電影評分:{movie_point}
            評價人數:{movie_num}'''

            f.write(str1)


# 獲取10個鏈接
n = 0
for line in range(10):
    url = f'https://movie.douban.com/top250?start={n}&filter='
    n += 25
    print(url)

    response = get_page(url)
    res_list_iter = parse_page(response.text)
    # print(res_list)
    save_data(res_list_iter)
  • logging
# logging的配置信息
"""
logging配置
"""
import os

import logging.config

# 定義三種日誌輸出格式 開始
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]' #其中name爲getlogger指定的名字

simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'


# 定義日誌輸出格式 結束
# ****************注意1: log文件的目錄
BASE_PATH = os.path.dirname(os.path.dirname(__file__))
logfile_dir = os.path.join(BASE_PATH, 'log_dir')
# print(logfile_dir)

# ****************注意2: log文件名
logfile_name = 'user.log'

# 若是不存在定義的日誌目錄就建立一個
if not os.path.isdir(logfile_dir):
    os.mkdir(logfile_dir)

# log文件的全路徑
logfile_path = os.path.join(logfile_dir, logfile_name)

# ****************注意3: log配置字典
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': simple_format
        },
    },
    'filters': {},
    'handlers': {
        #打印到終端的日誌
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'simple'
        },
        # 打印到文件的日誌,收集info及以上的日誌
        'default': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            'formatter': 'standard',
            'filename': logfile_path,  # 日誌文件
            'maxBytes': 1024*1024*5,  # 日誌大小 5M
            'backupCount': 5,
            'encoding': 'utf-8',  # 日誌文件的編碼,不再用擔憂中文log亂碼了
        },
    },
    'loggers': {
        #logging.getLogger(__name__)拿到的logger配置
        '': {
            'handlers': ['default', 'console'],  # 這裏把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕
            'level': 'DEBUG',
            'propagate': True,  # 向上(更高level的logger)傳遞
        },
    },
}


# 注意4:
def get_logger(user_type):
    # 1.加載log配置字典到logging模塊的配置中
    logging.config.dictConfig(LOGGING_DIC)

    # 2.獲取日誌對象
    # logger = logging.getLogger('user')
    # logger = logging.getLogger('bank')
    # logger = logging.getLogger('shop')
    logger = logging.getLogger(user_type)
    return logger

# logging.config.dictConfig(LOGGING_DIC)
# # 調用獲取日誌函數的到日誌對象
# logger = logging.getLogger('user')

# 經過logger日誌對象,調用內部的日誌打印
logger = get_logger('user')
# '只要思想不滑坡,方法總比問題多!'就是須要記錄的日誌信息
logger.info('學習不要浮躁,一步一個腳印!')
logger.info('只要思想不滑坡,方法總比問題多!')
  • 防止導入包是被自動執行
def func():
    print('from test1.func...')

# func()

# __name__屬於模塊名稱空間中的一個名字
# 當咱們執行該模塊時就會產生
print(__name__)  # 在當前文件中名字爲:__main__   被導入時: 模塊的名字

# 注意: 記住--》 main + 回車鍵

if __name__ == '__main__':
    print('在當前模塊下執行功能')
    func()
else:
    print('當前模塊已被導入')
  • 包的理論
5.包的理論
    - 奪命三問:
        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產生的名稱空間中。

相關文章
相關標籤/搜索