第六章 模塊

詳細模塊講解地址:https://www.cnblogs.com/wupeiqi/articles/5501365.htmlhtml

第六章 模塊

6.1 模塊的定義

  1. 模塊的定義
    • py文件 寫好了的 對程序員直接提供某方面功能的文件
  2. 包的定義
    • 文件夾 存儲了多個py文件的文件夾
    • 若是導入的是一個包,這個包裏的模塊默認是不能用的
    • 導入一個包至關於執行_ _ init _ _.py文件中的內容
  3. python2與python3的區別七
    • python2:文件夾中必須有_ _ init _ _.py文件
    • python3:不須要有_ _ init _ _.py文件
    • 建議:推薦之後寫代碼,不管是python2仍是python3,都要加上此文件

6.2 模塊的分類(類庫)

6.2.1 內置模塊

  • python內部提供的功能
  • 導入模塊後,直接使用便可

6.2.1.1 random

  • 隨機數模塊
  1. randint:獲得一個隨機數
import random    # 導入一個模塊 
v = random.randint(起始,終止)    # 獲得一個隨機數

#示例:生成隨機驗證碼
import random     
def get_random_code(length=6):
    data = []
    for i in range(length):
        v = random.randint(65,90)
        data.append(chr(v))
    return  ''.join(data)

code = get_random_code()
print(code)
  1. uniform:生成一個隨機小數
  2. choice:抽取一個對象
    • 應用:驗證碼、抽獎
  3. sample:抽取多個對象
    • 應用:一個獎項抽取多我的
  4. shuffle:打亂順序
    • 應用:洗牌、算法

6.2.1.2 hashlib

  • 摘要算法模塊
    • 密文驗證
    • 校驗文件的一致性
  1. md5
# 將指定的 「字符串」 進行 加密
import hashlib     # 導入一個模塊
def get_md5(data):          # md5 加密函數  
    obj = hashlib.md5()
    obj.update(data.encode('utf-8'))
    result = obj.hexdigest()
    return result
val = get_md5('123')
print(val)

# 加鹽
import hashlib
def get_md5(data):
    obj = hashlib.md5("sidrsdxff123ad".encode('utf-8'))            # 加鹽
    obj.update(data.encode('utf-8'))
    result = obj.hexdigest()
    return result
val = get_md5('123')
print(val)
# 應用:用戶註冊+用戶登陸
import hashlib
USER_LIST = []
def get_md5(data):                   # md5 加密函數 
    obj = hashlib.md5("12:;idrsicxwersdfsaersdfs123ad".encode('utf-8'))         # 加鹽
    obj.update(data.encode('utf-8'))
    result = obj.hexdigest()
    return result

def register():                      # 用戶註冊函數
    print('**************用戶註冊**************')
    while True:
        user = input('請輸入用戶名:')
        if user == 'N':
            return
        pwd = input('請輸入密碼:')
        temp = {'username':user,'password':get_md5(pwd)}
        USER_LIST.append(temp)

def login():                          # 用戶登陸函數
    print('**************用戶登錄**************')
    user = input('請輸入用戶名:')
    pwd = input('請輸入密碼:')
    for item in USER_LIST:
        if item['username'] == user and item['password'] == get_md5(pwd):
            return True

register()
result = login()
if result:
    print('登錄成功')
else:
    print('登錄失敗')
  1. shapython

    import hashlib
    md5 = hashlib.sha1('鹽'.encode())
    md5.update(b'str')
    print(md5.hexdigest())

6.2.1.3 getpass

  • 只能在終端運行
  1. getpass.getpass:輸入密碼時不顯示
import getpass        # 導入一個模塊
pwd = getpass.getpass('請輸入密碼:')
if pwd == '123':
    print('輸入正確')

6.2.1.4 time【經常使用】

  • 時間模塊
  1. time.time:時間戳(從1970年到如今經歷的秒數)mysql

    # https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=4ZwIFHM6iw==&tip=1&r=-781028520&_=1555559189206
  2. time.sleep:等待的秒數程序員

  3. time.timezoneweb

  • 示例正則表達式

    # 計算函數執行時間
    import time
    def wrapper(func):
        def inner():
            start_time = time.time()
            v = func()
            end_time = time.time()
            print(end_time-start_time)
            return v
        return inner
    @wrapper
    def func1():
        time.sleep(2)
        print(123)   
    func1()

6.2.1.5 datetime

  • 時間模塊
  1. datetime.now():當前本地時間redis

  2. datetime.utcnow():當前UTC時間算法

    import time,timezone,timedelta
    from datetime import datetime,timezone,timedelta
    # 獲取datetime格式時間
    # 當前本地時間
    v1 = datetime.now() 
    
    # 當前東7區時間
    tz = timezone(timedelta(hours=7)) 
    v2 = datetime.now(tz)
    
    # 當前UTC時間
    v3 = datetime.utcnow() 
    print(v3)
  • 相互轉換sql

    import time
    from datetime import datetime,timedelta
    # 1.datetime格式和字符串的相互轉換
    # 把datetime格式轉換成字符串:strftime
    v1 = datetime.now()
    val = v1.strftime("%Y-%m-%d %H:%M:%S")
    # 字符串轉成datetime格式:strptime
    v1 = datetime.strptime('2011-11-11','%Y-%m-%d')
    
    # 2.datetime時間的加減
    v1 = datetime.strptime('2011-11-11','%Y-%m-%d')
    v2 = v1 - timedelta(days=140)
    # 再轉換成字符串
    date = v2.strftime('%Y-%m-%d')
    
    # 3.時間戳和datetime的相互轉換
    # 時間戳轉換成datetime格式:fromtimestamp
    ctime = time.time()
    v1 = datetime.fromtimestamp(ctime)
    # datetime格式轉換成時間戳:timestamp
    v1 = datetime.now()
    val = v1.timestamp()

6.2.1.6 sys

  • python解釋器相關數據
  1. sys.getrefcount:獲取一個值的應用計數json

  2. sys.getrecursionlimit:python默認支持的遞歸數量

  3. sys.stdout.write:輸入輸出

    • 補充:\n:換行 \t:製表符 \r:回到當前行的起始位置

      import time
      for i in range(1,101):
          msg = "%s%%\r" %i
          print(msg,end='')
          time.sleep(0.05)
    • 示例:讀取文件的進度條

    import os
    # 1. 讀取文件大小(字節)
    file_size = os.stat('20190409_192149.mp4').st_size
    
    # 2.一點一點的讀取文件
    read_size = 0
    with open('20190409_192149.mp4',mode='rb') as f1,open('a.mp4',mode='wb') as f2:
        while read_size < file_size:
            chunk = f1.read(1024) # 每次最多去讀取1024字節
            f2.write(chunk)
            read_size += len(chunk)
            val = int(read_size / file_size * 100)
            print('%s%%\r' %val ,end='')
  4. sys.argv:獲取用戶執行腳本時,傳入的參數

    • 示例:讓用戶執行腳本傳入要刪除的文件路徑,在內部幫助用將目錄刪
    """
    讓用戶執行腳本傳入要刪除的文件路徑,在內部幫助用將目錄刪除。
    C:\Python36\python36.exe D:/code/s21day14/7.模塊傳參.py D:/test
    C:\Python36\python36.exe D:/code/s21day14/7.模塊傳參.py
    """
    
    import sys
    # 獲取用戶執行腳本時,傳入的參數。
    # C:\Python36\python36.exe D:/code/s21day14/7.模塊傳參.py D:/test
    # sys.argv = [D:/code/s21day14/7.模塊傳參.py, D:/test]
    path = sys.argv[1]
    
    # 刪除目錄
    import shutil
    shutil.rmtree(path)
  5. sys.exit(0):程序終止,0表明正常終止

  6. sys.path:默認python去導入模塊時,會按照sys.path中的路徑

    • 添加目錄:sys.path.append('目錄')
    import sys
    sys.path.append('D:\\goodboy')
  7. sys.modules:存儲了當前程序中用到的全部模塊,反射本文件中的內容

6.2.1.7 os【經常使用】

  • 和操做系統相關的數據
  1. os.path.exists(path):若是path存在,返回True;若是path不存在,返回False

  2. os.stat('文件路徑').st_size / os.path.getsize :獲取文件大小

  3. os.path.abspath():獲取一個文件的絕對路徑

    import os
    os.path.abspath(__file__)  #找到運行腳本的絕對路徑
    v1 = os.path.abspath(path)
    print(v1)
  4. os.path.dirname():獲取路徑的上級目錄

    import os
    v = r"D:\code\s21day14\20190409_192149.mp4"
    print(os.path.dirname(v))
    • 補充:轉義

      v1 = r"D:\code\s21day14\n1.mp4"  (推薦) 加了r就至關於轉義了
      v2 = "D:\\code\\s21day14\\n1.mp4"
  5. os.path.join:路徑的拼接

    import os
    path = "D:\code\s21day14" # user/index/inx/fasd/
    v = 'n.txt'
    result = os.path.join(path,v)
    print(result)
  6. os.listdir:查看一個目錄下全部的文件【第一層】

    import os
    result = os.listdir(r'D:\code\s21day14')
    for path in result:
        print(path)
  7. os.walk:查看一個目錄下全部的文件【全部層】

    import os
    result = os.walk(r'D:\code\s21day14')
    for a,b,c in result:
        # a,正在查看的目錄 b,此目錄下的文件夾  c,此目錄下的文件
        for item in c:
            path = os.path.join(a,item)
            print(path)
  8. os.makedir:建立目錄,只能生產一層目錄(基本不用這個)

  9. os.makedirs:建立目錄及其子目錄(推薦使用)

    # 將內容寫入指定文件中
    import os
    file_path = r'db\xx\xo\xxxxx.txt'
    file_folder = os.path.dirname(file_path)
    if not os.path.exists(file_folder):
        os.makedirs(file_folder)
    with open(file_path,mode='w',encoding='utf-8') as f:
        f.write('asdf')
  10. os.rename:重命名

    # 將db重命名爲sb
    import os
    os.rename('db','sb')
  11. os.path.isdir:判斷是不是文件夾

  12. os.path.isfile:判斷是不是文件

6.2.1.8 shutil

  • 用途:刪除、重命名、壓縮、解壓等
  1. shutil.rmtree(path):刪除目錄

    # 刪除目錄
    import shutil
    shutil.rmtree(path)
  2. shutil.move:重命名

    # 重命名
    import shutil
    shutil.move('test','ttt')
  3. shutil.make_archive:壓縮文件

    # 壓縮文件
    import shutil
    shutil.make_archive('zzh','zip','D:\code\s21day16\lizhong')
  4. shutil.unpack_archive:解壓文件

    # 解壓文件
    import shutil
    shutil.unpack_archive('zzh.zip',extract_dir=r'D:\code\xxxxxx\xxxx',format='zip')
  • 示例

    import os
    import shutil
    from datetime import datetime
    ctime = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
    # 1.壓縮lizhongwei文件夾 zip
    # 2.放到到 code 目錄(默認不存在)
    # 3.將文件解壓到D:\x1目錄中。
    if not os.path.exists('code'):
        os.makedirs('code')
    shutil.make_archive(os.path.join('code',ctime),'zip','D:\code\s21day16\lizhongwei')
    
    file_path = os.path.join('code',ctime) + '.zip'
    shutil.unpack_archive(file_path,r'D:\x1','zip')

6.2.1.9 json

  • json是一個特殊的字符串,長得像列表/字典/字符串/數字等嵌套
  • 序列化:把python中的值轉化爲json格式的字符串
  • 反序列化:將json格式的字符串轉換成python的數據類型
  • json格式要求:本質是字符串
    • 只包含 int / float / str / list / dict
    • 最外層必須是 list / dict 除去引號的最外層
    • 在json中,內部str必須是雙引號
    • 存在字典字典的key只能是str
    • 不能連續load屢次
  1. json.dumps():序列化

    • json只支持 dict / list / typle / str / int / float / True / False / None 序列化
    • 字典或列表中若是有中文,序列化時,若是想保留中文顯示
    import json
    v = {'k1':'alex','k2':'李傑'}
    val = json.dumps(v,ensure_ascii = False)  #ensure_ascii 保留中文
    #{"k1": "alex", "k2": "李傑"}
  2. json.loads():反序列化

    import json
    # 序列化,將python的值轉換爲json格式的字符串。
    v = [12,3,4,{'k1':'v1'},True,'asdf']
    v1 = json.dumps(v)
    print(v1)
    
    # 反序列化,將json格式的字符串轉換成python的數據類型
    v2 = '["alex",123]'
    print(type(v2))
    v3 = json.loads(v2)
    print(v3,type(v3))
  3. json.dump:打開文件,序列化後,寫入文件

    import json
    v = {'k1':'alex','k2':'李傑'}
    f = open('x.txt',mode='w',encoding='utf-8')
    val = json.dump(v,f)
    print(val)
    f.close()
  4. json.load:打開文件,讀取文件內容

    import json
    v = {'k1':'alex','k2':'李傑'}
    f = open('x.txt',mode='r',encoding='utf-8')
    data = json.load(f)
    f.close()
    print(data,type(data))

6.2.1.10 pickle

  • pickle與json的區別
    • json
      • 優勢:全部語言通用
      • 缺點:只能序列化基本的數據類型 list/dict 等
    • pickle
      • 優勢:python中全部的東西都能被他序列化(socket對象),支持連續load屢次
      • 缺點:序列化的內容只有python認識
  1. pickle.dumps:序列化

    • 序列化後的東西不可讀
  2. pickle.loads:反序列化

    import pickle
    # 序列化
    v = {1,2,3,4}
    val = pickle.dumps(v)
    print(val)
    
    # 反序列化
    data = pickle.loads(val)
    print(data,type(data))
  3. pickle.dump:寫入文件(注意:mode='wb')

  4. pickle.load:讀取文件(注意:mode='rb')

    import pickle
    # 寫入文件
    v = {1,2,3,4}
    f = open('x.txt',mode='wb')
    val = pickle.dump(v,f)
    f.close()
    
    # 讀取文件
    f = open('x.txt',mode='rb')
    data = pickle.load(f)
    f.close()
    print(data)

6.2.1.11 copy

  • 拷貝模塊
  1. copy.copy:淺拷貝

  2. copy.deepcopy:深拷貝

    import copy 
    v1 = [1,2,3]      
    v2 = copy.copy(v1)             #淺拷貝
    v3 = copy.deepcopy(v1)         #深拷貝

6.2.1.12 importlib

  1. importlib.import_module:經過字符串的形式導入模塊

    #示例一:
    import importlib
    # 用字符串的形式導入模塊。
    redis = importlib.import_module('utils.redis')
    
    # 用字符串的形式去對象(模塊)找到他的成員。
    getattr(redis,'func')()
    
    #示例二:
    import importlib
    middleware_classes = [
        'utils.redis.Redis',
        # 'utils.mysql.MySQL',
        'utils.mongo.Mongo'
    ]
    for path in middleware_classes:
        module_path,class_name = path.rsplit('.',maxsplit=1)
        module_object = importlib.import_module(module_path)# from utils import redis
        cls = getattr(module_object,class_name)
        obj = cls()
        obj.connect()

6.2.1.13 logging

  • 日誌模塊:記錄日誌的

    • 給用戶看的:流水類,如銀行流水
    • 給程序員看的:
      • 統計用的
      • 用來作故障排除的,debug
      • 用來記錄錯誤,完成代碼的優化
  • 日誌處理本質:Logger / FileHandler / Formatter

  • 兩種配置方式:

    • basicConfig

      • 優勢:使用方便
      • 缺點:不能實現編碼問題,不能同時向文件和屏幕上輸出
    • logger對象

      • 優勢:能實現編碼問題,能同時向文件和屏幕上輸出
      • 缺點:複雜
      • 示例:
      import logging
      # 建立一個logger對象
      logger = logging.getLogger()
      # 建立一個文件操做符
      fh = logging.FileHandler('log.log')
      # 建立一個屏幕操做符
      sh = logging.StreamHandler()
      # 給logger對象綁定 文件操做符
      logger.addHandler(fh)
      # 給logger對象綁定 屏幕操做符
      logger.addHandler(sh)
      # 建立一個格式
      formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
      # 給文件操做符 設定格式
      fh.setFormatter(formatter)
      # 給屏幕操做符 設定格式
      sh.setFormatter(formatter)
      # 用logger對象來操做
      logger.warning('message')
  • 日誌異常級別

    CRITICAL = 50       # 崩潰
    FATAL = CRITICAL
    ERROR = 40          # 錯誤
    WARNING = 30
    WARN = WARNING
    INFO = 20
    DEBUG = 10
    NOTSET = 0
  • 推薦處理日誌方式

    import logging
    
    file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',)
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        handlers=[file_handler,],
        level=logging.ERROR
    )
    
    logging.error('你好')
  • 推薦處理日誌方式 + 日誌分割

    import time
    import logging
    from logging import handlers
    # file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',)
    file_handler = handlers.TimedRotatingFileHandler(filename='x3.log', when='s', interval=5, encoding='utf-8')
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        handlers=[file_handler,],
        level=logging.ERROR
    )
    
    for i in range(1,100000):
        time.sleep(1)
        logging.error(str(i))

    注意事項:

    # 在應用日誌時,若是想要保留異常的堆棧信息。
    import logging
    import requests
    
    logging.basicConfig(
        filename='wf.log',
        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        level=logging.ERROR
    )
    
    try:
        requests.get('http://www.xxx.com')
    except Exception as e:
        msg = str(e) # 調用e.__str__方法
        logging.error(msg,exc_info=True)

6.2.1.14 collections

  1. OrderedDict:有序字典

    from collections import OrderedDict
    odic = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
    print(odic)
    for k in odic:
        print(k,odic[k])
  2. defaultdict:默認字典

  3. deque:雙端隊列

  4. namedtuple:可命名元組

    # 建立一個類,這個類沒有方法,全部屬性的值都不能修改
    from collections import namedtuple       # 可命名元組
    Course = namedtuple('Course',['name','price','teacher'])
    python = Course('python',19800,'alex')
    print(python)
    print(python.name)
    print(python.price)

6.2.1.15 re

正則表達式
  1. 定義
  • 定義:正則表達式是一種規則匹配字符串的規則
  • re模塊自己只是用來操做正則表達式的,和正則自己不要緊
  • 爲何要有正則表達式?
    • 匹配字符串
      • 一我的的電話號碼
      • 一我的的身份證號
      • 一臺機器的ip地址
    • 表單驗證
      • 驗證用戶輸入的信息是否準確
      • 銀行卡號
    • 爬蟲
      • 從網頁源碼中獲取一些連接、重要數據
  1. 正則規則
  • 第一條規則 : 自己是哪個字符,就匹配字符串中的哪個字符
  • 第二條規則 : 字符組[字符1字符2],一個字符組就表明匹配一個字符,只要這個字符出如今字符組裏,那麼就說明這個字符能匹配上
    • 字符組中還可使用範圍
    • 全部的範圍都必須遵循ascii碼從下到大來指定
    • 經常使用:[0-9] [a-z] [A-Z]
  1. 元字符
  • \d:表示全部的數字
    • \是轉義符 轉義符轉義了d,讓d可以匹配全部0-9之間的數
  • \w:表示大小寫字母、數字、下劃線
  • \s:表示空白、空格、換行符、製表符
  • \t:匹配製表符
  • \n:匹配換行符
  • \D:表示全部的非數字
  • \W:表示除數字、字母、下劃線以外的全部字符
  • \S:表示非空白
  • . :表示除了換行符以外的任意內容
  • [] 字符組:只要在中括號內的全部字符都是符合規則的字符
  • [^ ]非字符組:只要在中括號內的全部字符都是不符合規則的字符
  • ^:表示一個字符的開始
  • $:表示一個字符的結束
  • |:表示或
    • 注意:若是兩個規則有重疊部分,老是長的在前面,短的在後面
  • ():表示分組,給一部分正則規定爲一組,|這個符號的做用域就能夠縮小了
  • 特殊:
    • [\d]、[0-9]、\d:沒有區別 都是要匹配一位數字
    • [\d\D]、[\W\w]、[\S\s] 匹配全部一切字符
  1. 量詞
  • {n}:表示只能出現n次
  • {n,}:表示至少出現n次
  • {n,m}:表示至少出現n次,至多出現m次
  • ?:表示匹配0次或1次,表示無關緊要,可是有隻能有一個,好比小數點
  • +:表示匹配1次或屢次
  • *:表示匹配0次或屢次,表示無關緊要,可是有能夠有多個好比小數點後n位
  • 匹配0次出現的狀況:
    • 匹配任意的保留兩位小數的數字
    • 匹配一個整數或者小數
  1. 貪婪匹配
  • 默認貪婪匹配,老是會在符合量詞條件的範圍內儘可能多匹配
  • 非貪婪匹配 :惰性匹配
    • 老是匹配符合條件範圍內儘可能小的字符串
    • 格式:元字符 量詞 ? x
      • 表示按照元字符規則在量詞範圍內匹配,一旦遇到x就中止
      • 示例:.*?x 匹配任意的內容任意屢次遇到x就當即中止
  1. 轉義符:
  • 正則表達式中的轉義符在python的字符串中也恰好有轉移的做用
  • 可是正則表達式中的轉義符和字符串中的轉義符並不要緊,且還容易有衝突
  • 爲了不這種衝突,咱們全部的正則都以在工具中的測試結果爲結果
  • 而後只須要在正則和待匹配的字符串外面都加r便可
郵箱規則
@以前必須有內容且只能是字母(大小寫)、數字、下劃線(_)、減號(-)、點(.)
@和最後一個點(.)之間必須有內容且只能是字母(大小寫)、數字、點(.)、減號(-),且兩個點不能挨着
最後一個點(.)以後必須有內容且內容只能是字母(大小寫)、數字且長度爲大於等於2個字節,小於等於6個字節

郵箱驗證的正則表達式:
^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$
正則模塊
  1. re.findall:會匹配字符串中全部符合規則的項,並返回一個列表,若是沒匹配到,返回空列表

    import re
    ret = re.findall('\d+','alex83')
    print(ret)
    # findall 會匹配字符串中全部符合規則的項
    # 並返回一個列表
    # 若是未匹配到返回空列表
  2. re.search:若是匹配到,返回一個對象,用group取值,若是沒匹配到,返回None,不能用group

    import re
    ret = re.search('\d+','alex83')
    print(ret)                 # 若是能匹配上返回一個對象,若是不能匹配上返回None
    if ret:
        print(ret.group())     # 若是是對象,那麼這個對象內部實現了group,因此能夠取值
                               # 若是是None,那麼這個對象不可能實現了group方法,因此報錯
    # 會從頭至尾從帶匹配匹配字符串中取出第一個符合條件的項
    # 若是匹配到了,返回一個對象,用group取值
    # 若是沒匹配到,返回None,不能用group
  3. re.match:match = search + ^正則

    import re
    ret = re.match('\d','alex83') == re.match('^\d','alex83')
    print(ret)
    # 會從頭匹配字符串,從第一個字符開始是否符合規則
    # 若是符合,就返回對象,用group取值
    # 若是不符合,就返回None
  4. re.finditer:在查詢的結果超過1個的狀況下,可以有效的節省內存,下降空間複雜度,從而也下降了時間複雜度

    import re
    ret = re.finditer('\d','safhl02urhefy023908'*20000000)  # ret是迭代器
    for i in ret:    # 迭代出來的每一項都是一個對象
        print(i.group())  # 經過group取值便可
  5. re.compile:在同一個正則表達式重複使用屢次的時候使用可以減小時間的開銷

    import re
    ret = re.compile('\d+')
    r1 = ret.search('alex83')
    r2 = ret.findall('wusir74')
    r3 = ret.finditer('taibai40')
    for i in r3:
        print(i.group())
  6. re.split:利用正則規則進行切割

    import re
    ret = re.split('\d(\d)','alex83wusir74taibai')  # 默認自動保留分組中的內容
    print(ret)
  7. re.sub / re.subn:利用正則規則進行替換

    import re
    ret = re.sub('\d','D','alex83wusir74taibai',1)
    print(ret)      # 'alexD3wusir74taibai'
    
    ret = re.subn('\d','D','alex83wusir74taibai')
    print(ret)      # ('alexDDwusirDDtaibai', 4)
  • 分組和re模塊
  1. 關於group取值

    import re
    ret = re.search('<(\w+)>(.*?)</\w+>',s1)
    print(ret)
    print(ret.group(0))   # group參數默認爲0 表示取整個正則匹配的結果
    print(ret.group(1))   # 取第一個分組中的內容
    print(ret.group(2))   # 取第二個分組中的內容
  2. 分組命名:(?P <名字> 正則表達式)

    import re
    ret = re.search('<(?P<tag>\w+)>(?P<cont>.*?)</\w+>',s1)
    print(ret)
    print(ret.group('tag'))   # 取tag分組中的內容
    print(ret.group('cont'))   # 取cont分組中的內容
  3. 引用分組:(?P=組名) 這個組中的內容必須徹底和以前已經存在的組匹配到的內容如出一轍

    import re
    # 方法一:
    s = '<h1>wahaha</h1>'
    ret = re.search('<(?P<tag>\w+)>.*?</(?P=tag)>',s)
    print(ret.group('tag'))      # 'h1'
    
    # 方法二:
    s = '<h1>wahaha</h1>'
    ret = re.search(r'<(\w+)>.*?</\1>',s)
    print(ret.group(1))          # 'h1'
  4. 分組和findall:默認findall 優先顯示分組內的內容,取消分組優先顯示 :(?:正則)

    import re
    ret = re.findall('\d(\d)','aa1alex83')
    # findall遇到正則表達式中的分組,會優先顯示分組中的內容
    print(ret)
    
    # 取消分組優先顯示:
    ret = re.findall('\d+(?:\.\d+)?','1.234+2')
    print(ret)
  5. 有的時候咱們想匹配的內容包含在不相匹配的內容當中,這個時候只須要把不想匹配的先匹配出來,再經過手段去掉

    import re
    ret=re.findall(r"\d+\.\d+|(\d+)","1-2*(60+(-40.35/5)-(-4*3))")
    print(ret)       # ['1', '2', '60', '', '5', '4', '3']
    ret.remove('')
    print(ret)       # ['1', '2', '60', '5', '4', '3']
  • 爬蟲示例

    # 方法一:
    import re
    import json
    import requests
    
    def parser_page(par,content):
        res = par.finditer(content)
        for i in res:
            yield {'id': i.group('id'),
                   'title': i.group('title'),
                   'score': i.group('score'),
                   'com_num': i.group('comment_num')}
    
    def get_page(url):
        ret = requests.get(url)
        return  ret.text
    
    
    pattern = '<div class="item">.*?<em class="">(?P<id>\d+)</em>.*?<span class="title">(?P<title>.*?)</span>.*?' \
                  '<span class="rating_num".*?>(?P<score>.*?)</span>.*?<span>(?P<comment_num>.*?)人評價</span>'
    par = re.compile(pattern,flags=re.S)
    num = 0
    with open('movie_info',mode = 'w',encoding='utf-8') as f:
        for i in range(10):
            content = get_page('https://movie.douban.com/top250?start=%s&filter=' % num)
            g = parser_page(par,content)
            for dic in g:
                f.write('%s\n'%json.dumps(dic,ensure_ascii=False))
            num += 25
    # 方法二:進階
    import re
    import json
    import requests
    
    def parser_page(par,content):
        res = par.finditer(content)
        for i in res:
            yield {'id': i.group('id'),
                   'title': i.group('title'),
                   'score': i.group('score'),
                   'com_num': i.group('comment_num')}
    
    def get_page(url):
        ret = requests.get(url)
        return  ret.text
    
    def write_file(file_name):
        with open(file_name,mode = 'w',encoding='utf-8') as f:
            while True:
                dic = yield
                f.write('%s\n' % json.dumps(dic, ensure_ascii=False))
    
    pattern = '<div class="item">.*?<em class="">(?P<id>\d+)</em>.*?<span class="title">(?P<title>.*?)</span>.*?' \
                  '<span class="rating_num".*?>(?P<score>.*?)</span>.*?<span>(?P<comment_num>.*?)人評價</span>'
    par = re.compile(pattern,flags=re.S)
    num = 0
    f = write_file('move2')
    next(f)
    for i in range(10):
        content = get_page('https://movie.douban.com/top250?start=%s&filter=' % num)
        g = parser_page(par,content)
        for dic in g:
            f.send(dic)
        num += 25
    f.close()

6.2.2 第三方模塊

6.2.2.1 基本知識

  • 須要下載安裝後才能導入使用

  • 安裝方式:

    • pip包管理工具
    # 把pip.exe 所在的目錄添加到環境變量中。
    pip install 要安裝的模塊名稱  # pip install xlrd
    • 源碼安裝
    # 下載源碼包(壓縮文件) -> 解壓 -> 打開cmd窗口,並進入此目錄:cd C:\Python37\Lib\site-packages
    # 執行:python3 setup.py build
    # 執行:python3 setup.py install
  • 安裝路徑:C:\Python37\Lib\site-packages

6.2.2.2 經常使用的第三方模塊

  1. requests
  2. xlrd

6.2.3 自定義模塊

  • 本身寫的 xx.py

    def f1():
        print('f1')
    
    def f2():
        print('f2')
  • 在yy.py中調用

    # 調用自定義模塊中的功能
    import xx
    xx.f1()
    xx.f2()
  • 運行

    python yy.py

6.3 模塊的調用

注意:文件和文件夾的命名不能是導入的模塊名稱相同,不然就會直接在當前目錄中查找

6.3.1 絕對導入

1.模塊的基本導入及調用

  • 導入XXX.py文件
  • 方式一
# 導入模塊,加載此模塊中全部的值到內存。
import XXX

# 調用模塊中的函數
XXX.func()
  • 方式二
# 導入XXX.py中的func和show
from XXX import func,show

# 導入XXX.py中的全部值
from XXX import *

# 調用模塊中的函數
func()
  • 方式三
# 若是有重名狀況,就導入時起一個別名
# 導入XXX.py中的func,並起一個別名爲f
from XXX import func as f

# 調用模塊中的函數
f()
  • 總結

    • 導入:import 模塊,調用:模塊.函數()
    • 導入:from 模塊 import 函數,調用:函數()
    • 導入:from 模塊 import 函數 as 別名,調用:別名()
    • 知識點:
      • as:起別名
      • *:表明所有
  • 補充

    • 屢次導入再也不從新加載

      import jd # 第一次加載:會加載一遍jd中全部的內容。
      import jd # 由已經加載過,就再也不加載。
      print(456)
    • 非要從新加載

      import importlib
      import jd
      importlib.reload(jd)
      print(456)
  1. 導入文件夾中的py文件及調用
  • 導入YYY文件夾中的XXX.py文件
  • 方式一
# 導入模塊
import YYY.XXX

# 調用模塊中的函數
XXX.func()
  • 方式二
# 導入模塊
from YYY import XXX

# 調用模塊中的函數
XXX.func()
  • 方式三
# 導入模塊
from YYY.XXX import func

# 調用模塊中的函數
func()
  1. 總結
  • 模塊和要執行的py文件在同一目錄 且 須要 模塊中的不少功能時,推薦用:
    • 導入:import 模塊,調用:模塊.函數()
  • 其餘推薦:
    • 導入:from 模塊 import 模塊,調用:模塊.函數()
    • 導入:from 模塊.模塊 import 函數,調用:函數()

6.3.2 相對導入(不推薦)

from . import xxx
from .. import xxx
相關文章
相關標籤/搜索