1. 程式人生 > >Python開發系列課程(14)

Python開發系列課程(14)

玩轉正則表示式

正則表示式相關知識

在編寫處理字串的程式或網頁時,經常會有查詢符合某些複雜規則的字串的需要,正則表示式就是用於描述這些規則的工具,換句話說正則表示式是一種工具,它定義了字串的匹配模式(如何檢查一個字串是否有跟某種模式匹配的部分或者從一個字串中將與模式匹配的部分提取出來或者替換掉)。如果你在Windows作業系統中使用過檔案查詢並且在指定檔名時使用過萬用字元(*和?),那麼正則表示式也是與之類似的用來進行文字匹配的工具,只不過比起萬用字元正則表示式更強大,它能更精確地描述你的需求(當然你付出的代價是書寫一個正則表示式比打出一個萬用字元要複雜得多,要知道任何給你帶來好處的東西都是有代價的,就如同學習一門程式語言一樣),比如你可以編寫一個正則表示式,用來查詢所有以0開頭,後面跟著2-3個數字,然後是一個連字號“-”,最後是7或8位數字的字串(像028-12345678或0813-7654321),這不就是國內的座機號碼嗎。最初計算機是為了做數學運算而誕生的,處理的資訊基本上都是數值,而今天我們在日常工作中處理的資訊基本上都是文字資料,我們希望計算機能夠識別和處理符合某些模式的文字,正則表示式就顯得非常重要了。今天幾乎所有的程式語言都提供了對正則表示式操作的支援,Python通過標準庫中的re模組來支援正則表示式操作。

我們可以考慮下面一個問題:我們從某個地方(可能是一個文字檔案,也可能是網路上的一則新聞)獲得了一個字串,希望在字串中找出手機號和座機號。當然我們可以設定手機號是11位的數字(注意並不是隨機的11位數字,因為你沒有見過“25012345678”這樣的手機號吧)而座機號跟上一段中描述的模式相同,如果不使用正則表示式要完成這個任務就會很麻煩。

關於正則表示式的相關知識,大家可以閱讀一篇非常有名的部落格叫《正則表示式30分鐘入門教程》,讀完這篇文章後你就可以看懂下面的表格,這是我們對正則表示式中的一些基本符號進行的扼要總結。

符號 解釋 示例 說明
. 匹配任意字元 b.t 可以匹配bat / but / b#t / b1t等
\w 匹配字母/數字/下劃線 b\wt 可以匹配bat / b1t / b_t等
但不能匹配b#t
\s 匹配空白字元(包括\r、\n、\t等) love\syou 可以匹配love you
\d 匹配數字 \d\d 可以匹配01 / 23 / 99等
\b 匹配單詞的邊界 \bThe\b
^ 匹配字串的開始 ^The 可以匹配The開頭的字串
||.exe 可以匹配.exe結尾的字串
\W 匹配非字母/數字/下劃線 b\Wt 可以匹配b#t / [email protected]
但不能匹配but / b1t / b_t等
\S 匹配非空白字元 love\Syou 可以匹配love#you等
但不能匹配love you
\D 匹配非數字 \d\D 可以匹配9a / 3# / 0F等
\B 匹配非單詞邊界 \Bio\B
[] 匹配來自字符集的任意單一字元 [aeiou] 可以匹配任一母音字母字元
[^] 匹配不在字符集中的任意單一字元 [^aeiou] 可以匹配任一非母音字母字元
* 匹配0次或多次 \w*
+ 匹配1次或多次 \w+
? 匹配0次或1次 \w?
{N} 匹配N次 \w{3}
{M,} 匹配至少M次 \w{3,}
{M,N} 匹配至少M次至多N次 \w{3,6}
| 分支 foo|bar 可以匹配foo或者bar
(?#) 註釋
(exp) 匹配exp並捕獲到自動命名的組中
(?<name>exp) 匹配exp並捕獲到名為name的組中
(?:exp) 匹配exp但是不捕獲匹配的文字
(?=exp) 匹配exp前面的位置 \b\w+(?=ing) 可以匹配I’m dancing中的danc
(?<=exp) 匹配exp後面的位置 (?<=\bdanc)\w+\b 可以匹配I love dancing and reading中的第一個ing
(?!exp) 匹配後面不是exp的位置
(? 匹配前面不是exp的位置
*? 重複任意次,但儘可能少重複 a.*b
a.*?b
將正則表示式應用於aabab,前者會匹配整個字串aabab,後者會匹配aab和ab兩個字串
+? 重複1次或多次,但儘可能少重複
?? 重複0次或1次,但儘可能少重複
{M,N}? 重複M到N次,但儘可能少重複
{M,}? 重複M次以上,但儘可能少重複

說明:如果需要匹配的字元是正則表示式中的特殊字元,那麼可以使用\進行轉義處理,例如想匹配小數點可以寫成\.就可以了,因為直接寫.會匹配任意字元;同理,想匹配圓括號必須寫成\(和\),否則圓括號被視為正則表示式中的分組。

Python對正則表示式的支援

Python提供了re模組來支援正則表示式相關操作,下面是re模組中的核心函式。

函式 說明
compile(pattern, flags=0) 編譯正則表示式返回正則表示式物件
match(pattern, string, flags=0) 用正則表示式匹配字串 成功返回匹配物件 否則返回None
search(pattern, string, flags=0) 搜尋字串中第一次出現正則表示式的模式 成功返回匹配物件 否則返回None
split(pattern, string, maxsplit=0, flags=0) 用正則表示式指定的模式分隔符拆分字串 返回列表
sub(pattern, repl, string, count=0, flags=0) 用指定的字串替換原字串中與正則表示式匹配的模式 可以用count指定替換的次數
fullmatch(pattern, string, flags=0) match函式的完全匹配(從字串開頭到結尾)版本
findall(pattern, string, flags=0) 查詢字串所有與正則表示式匹配的模式 返回字串的列表
finditer(pattern, string, flags=0) 查詢字串所有與正則表示式匹配的模式 返回一個迭代器
purge() 清除隱式編譯的正則表示式的快取
re.I / re.IGNORECASE 忽略大小寫匹配標記
re.M / re.MULTILINE 多行匹配標記

說明:上面提到的re模組中的這些函式,實際開發中也可以用正則表示式物件的方法替代對這些函式的使用,如果一個正則表示式需要重複的使用,那麼先通過compile函式編譯正則表示式並創建出正則表示式物件無疑是更為明智的選擇。

下面我們通過一系列的例子來告訴大家在Python中如何使用正則表示式。

例子1:驗證輸入使用者名稱和QQ號是否有效並給出對應的提示資訊。

"""

驗證輸入使用者名稱和QQ號是否有效並給出對應的提示資訊

要求:
使用者名稱必須由字母、數字或下劃線構成且長度在6~20個字元之間
QQ號是5~12的數字且首位不能為0

"""

import re


def main():
    username = input('請輸入使用者名稱: ')
    qq = input('請輸入QQ號: ')
    # match函式的第一個引數是正則表示式字串或正則表示式物件
    # 第二個引數是要跟正則表示式做匹配的字串物件
    m1 = re.match(r'^[0-9a-zA-Z_]{6,20}$', username)
    if not m1:
        print('請輸入有效的使用者名稱.')
    m2 = re.match(r'^[1-9]\d{4,11}$', qq)
    if not m2:
        print('請輸入有效的QQ號.')
    if m1 and m2:
        print('你輸入的資訊是有效的!')


if __name__ == '__main__':
    main()

提示:上面在書寫正則表示式時使用了“原始字串”的寫法(在字串前面加上了r),所謂“原始字串”就是字串中的每個字元都是它原始的意義,說得更直接一點就是字串中沒有所謂的轉義字元啦。因為正則表示式中有很多元字元和需要進行轉義的地方,如果不使用原始字串就需要將反斜槓寫作\\,例如表示數字的\d得書寫成\\d,這樣不僅寫起來不方便,閱讀的時候也會很吃力。

例子2:從一段文字中提取出國內手機號碼。

下面這張圖是截止到2017年底,國內三家運營商推出的手機號段。

這裡寫圖片描述

import re


def main():
    # 建立正則表示式物件 使用了前瞻和回顧來保證手機號前後不應該出現數字
    pattern = re.compile(r'(?<=\D)1[34578]\d{9}(?=\D)')
    sentence = '''
    重要的事情說8130123456789遍,我的手機號是13512346789這個靚號,
    不是15600998765,也是110或119,王大錘的手機號才是15600998765。
    '''
    # 查詢所有匹配並儲存到一個列表中
    mylist = re.findall(pattern, sentence)
    print(mylist)
    print('--------華麗的分隔線--------')
    # 通過迭代器取出匹配物件並獲得匹配的內容
    for temp in pattern.finditer(sentence):
        print(temp.group())
    print('--------華麗的分隔線--------')
    # 通過search函式指定搜尋位置找出所有匹配
    m = pattern.search(sentence)
    while m:
        print(m.group())
        m = pattern.search(sentence, m.end())


if __name__ == '__main__':
    main()

說明:上面匹配國內手機號的正則表示式並不夠好,因為像14開頭的號碼只有145或147,而上面的正則表示式並沒有考慮這種情況,要匹配國內手機號,更好的正則表示式的寫法是:(?<=\D)(1[38]\d{9}|14[57]\d{8}|15[0-35-9]\d{8}|17[678]\d{8})(?=\D),國內最近好像有19和16開頭的手機號了,但是這個暫時不在我們考慮之列。

例子3:替換字串中的不良內容

import re


def main():
    sentence = '你丫是傻叉嗎? 我操你大爺的. Fuck you.'
    purified = re.sub('[操肏艹草曹]|fuck|shit|傻[比屄逼叉缺吊屌]|煞筆',
                      '*', sentence, flags=re.IGNORECASE)
    print(purified)  # 你丫是*嗎? 我*你大爺的. * you.


if __name__ == '__main__':
    main()

說明:re模組的正則表示式相關函式中都有一個flags引數,它代表了正則表示式的匹配標記,可以通過該標記來指定匹配時是否忽略大小寫、是否進行多行匹配、是否顯示除錯資訊等。如果需要為flags引數指定多個值,可以使用按位或運算子進行疊加,如flags=re.I | re.M

例子4:拆分長字串

import re


def main():
    poem = '窗前明月光,疑是地上霜。舉頭望明月,低頭思故鄉。'
    sentence_list = re.split(r'[,。, .]', poem)
    while '' in sentence_list:
        sentence_list.remove('')
    print(sentence_list)  # ['窗前明月光', '疑是地上霜', '舉頭望明月', '低頭思故鄉']


if __name__ == '__main__':
    main()

後話

如果要從事爬蟲類應用的開發,那麼正則表示式一定是一個非常好的助手,因為它可以幫助我們迅速的從網頁程式碼中發現某種我們指定的模式並提取出我們需要的資訊,當然對於初學者來收,要編寫一個正確的適當的正則表示式可能並不是一件容易的事情(當然有些常用的正則表示式可以直接在網上找找),所以實際開發爬蟲應用的時候,有很多人會選擇Beautiful SoupLxml來進行匹配和資訊的提取,前者簡單方便但是效能較差,後者既好用效能也好,但是安裝稍嫌麻煩,這些內容我們會在後期的爬蟲專題中為大家介紹。

相關推薦

Python開發系列課程(14)

玩轉正則表示式 正則表示式相關知識 在編寫處理字串的程式或網頁時,經常會有查詢符合某些複雜規則的字串的需要,正則表示式就是用於描述這些規則的工具,換句話說正則表示式是一種工具,它定義了字串的匹配模式(如何檢查一個字串是否有跟某種模式匹配的部分或者從一個字

Python開發系列課程(12)

圖形使用者介面和遊戲開發 基於tkinter模組的GUI GUI是圖形使用者介面的縮寫,圖形化的使用者介面對使用過計算機的人來說應該都不陌生,在此也無需進行贅述。Python預設的GUI開發模組是tkinter(在Python 3以前的版本中名為Tkin

Python開發系列課程(17)

Python“慣例” “慣例”這個詞指的是“習慣的做法,常規的辦法,一貫的做法”,與這個詞對應的英文單詞叫“idiom”。由於Python跟其他很多程式語言在語法和使用上還是有比較顯著的差別,因此作為一個Python開發者如果不能掌握這些慣例,就無法寫出“Py

iOS開發系列課程預告

理解 一點 super tin 使用 希望 應該 字符 one 近期在Mac和iOS上做開發,認為應該寫一點東西分享給感興趣的童鞋們。在此之前。以前有非常多同行們都在埋怨蘋果Objective-C的復雜和難以上手,為此也有非常多人對今年(2014年)剛推出的Swif

想做Python開發,這14種常用Python模組,你需知道的幾大模組!

    一、模組介紹 1. 定義: 模組:本質就是.py結尾的python檔案(檔名:test.py,對應的模組名:test) 用來從邏輯上組織python程式碼(變數,函式,類,邏輯:實現一個功能) 更多幹貨分享加python程式語言學習QQ群 5

Java Web開發系列課程

一·Java Web開發系列課程:SpringMVC框架入門 Spring MVC屬於SpringFrameWork的後續產品,已經融合在Spring Web Flow裡面。Spring 框架提供了構建 Web 應用程式的全功能 MVC 模組。 在使用Spring進行WEB開發時,可以選擇使

循序漸進學.Net Core Web Api開發系列14】:異常處理

系列目錄 一、概述 本篇介紹異常處理的知識。由於異常處理的技術應用並不複雜,本篇更多討論異常處理的一些理論知識,包括一些原則、約定和建議。 二、異常處理的基本原則 在Win32API程式設計中是沒有異常處理機制的,函式一般都是通過返回一個BOOL型的狀態碼來表達處理是否成功,比如需要通

iOS開發系列課程(01) --- iOS程式設計入門

iOS概述 什麼是iOS   iOS是蘋果公司為它的移動裝置(iPhone、iPad、iWatch等)開發的移動作業系統。 iOS發展史 2007年蘋果釋出iPhone Runs OS X 2008年更名iPhone OS 2010年更名iOS

使用Python-Flask框架開發Web網站系列課程(四)構建前端

前言 使用IDE:PyCharm 作業系統:Mac Python的版本:3.6 我的郵箱:[email protected] 交流群:372430835 說明: 本次課程的GitHub程式碼在最下面。 本次課程基於上個課程的程式碼,如果沒看過的請先傳

Python開發MapReduce系列(一)WordCount Demo

logs 3-9 line counter ota python開發 home num brush  原創,轉發請註明出處。   MapReduce是hadoop這只大象的核心,Hadoop 中,數據處理核心就是 MapReduce 程序設計模型。一個Map/Reduc

spark2.x由淺入深深到底系列五之python開發spark環境配置

spark 大數據 rdd 開發環境 python 學習spark任何的技術前,請先正確理解spark,可以參考: 正確理解spark以下是在mac操作系統上配置用python開發spark的環境一、安裝pythonspark2.2.0需要python的版本是Python2.6+ 或者 P

Android GIS開發系列-- 入門季(14)FeatureLayer之範圍查詢

sso 偏差 .get http pri tex des else uil Android GIS開發系列-- 入門季(5),這篇文章中,我們知道如何去查找要素。現在有一個需求,查找某點5000米範圍的要素,那如何來做呢?首先我們需要在地圖上畫個5000米半徑的圓,然後根據

測試開發系列Python開發mock接口(三)

有一個 cep 內置 stat 遊標 tab lB 端口號 HERE 於進入主題了,前面的準備工作都已經做好了,下面就開始寫邏輯的代碼了,代碼我已經寫好了,每行都加了註釋,不明白的可以留言。 1 2 3 4 5 6 7 8 9 10 11 12 13

Python開發入門14天集訓營·第1章Python基礎語法-編寫登陸認證程序

password put mod 基礎語 aps author one display 退出程序 作業題目: 編寫登陸認證程序 作業需求: 基礎需求: 讓用戶輸入用戶名密碼 認證成功後顯示歡迎信息 輸錯三次後退出程序 升級需求: 可以支持多個用戶登錄 (提示,通過列表

2018-5-21-Python全棧開發day9-Python開發課程簡介part1

課程 目標 運維 溝通 工程 作文 都是 網絡工程 怎麽 1.linux基礎 1.1開發的三種實現方式 運維:對計算機進行維護,保持計算機的正常運行 網絡:網絡工程師,將開發的軟件放到網絡上,進行交互 軟件開發:按照需求完成軟件的開發 2.Python開發 2.1Pytho

劉國柱- Unity遊戲開發深度學習 系列課程福利大放送

Unity課程送書 Unity套餐課程 Unity遊戲深度學習 Unity最新書籍贈送 Unity專題課程 劉國柱--Unity遊戲開發深度學習 系列課程福利大發送!不單優惠, 還送Unity最新版本必備實戰書籍! HI, 各位熱心的Unity愛好者與學員,《Unity3D/2D 遊戲開

Python爬蟲開發系列之一》開發IDE安裝

開發 size 環境配置 技術 keyword -s www 版本 是不是 中國有句古話說:工欲善其事,必先利其器! 在我最開始學 Python 的時候,因為沒有去探索好用的工具,吃了很多苦頭。磕磕絆絆走過來之後才知道,好的工具給效率帶來的提升不是從 1 到 1.1 倍速

Python系列課程——人工智能篇簡單入門

卷積 發展 學習 自然 歷史 手寫體識別 自然語言處理技術 一個 編寫 1、基礎篇——基於Python的機器學習>>>>>>戳我,立即學習 現在大熱、為未來計算機科學發展方向的機器學習了解多少呢? 下面推薦的這個內容比較適合小白,

後盾 React Native 開發系列視訊課程

161 安卓打包及名稱圖示的設定 課程結語-fadsf5686.mp4 160 安卓apk打包的環境配置方式-fadsf5686.mp4 159 微信和支付寶支付的實現流程-fadsf5686.mp4 158 訂單列表資料的處理-fdae87dfa.mp4 157 登陸後返回訂單介面的功能處理-fd

Python開發程式設計入門培訓課程——模組學習

  Python程式設計中的模組指的是什麼呢?Python程式設計入門培訓給大家分享下有關模組的知識。   模組簡單說就是一堆程式碼實現某個功能,Python為開發人員提供了豐富的模組,通過這些模組,我們可以快速開發出功能強大的程式。   具體來說Python模組有什麼用?   1、模組內有許多函式