一、正則表達式
正則表達式(regular expression)(regex)(RE),用來簡潔表達一組字符的表達式,由字符和操作符構成。
通用的字符串表達框架
簡潔表達一組字符串的表達式
針對字符串表達“簡潔”和“特征”思想的工具
判斷某字符串的特征歸屬
正則表達式常用於文本處理
表達文本類型的特征(病毒、入侵等)
同時查找或替換一組字符串
匹配字符串的全部或部分
正則表達式的使用
編譯:將符合正則表達式語法的字符串轉換為正則表達式特征
正則表達式的常用操作符
操作符 | 說明 | 實例 |
. | 表示任何單個字符(默認除換行符) | |
[] | 字符集,對單個字符給出取值范圍 | [abc]表示a、b、c,[a-z]表示a到z的單個字符 |
[^] | 非字符集,對單個字符給出排除范圍 | [^abc]表示非a或非b或非c的單個字符 |
* | 前一個字符0次或無限次擴展 | abc*表示ab、abc、abcc、abccc等 |
+ | 前一個字符1次或無限次擴展 | abc+表示abc、abcc、abccc等 |
? | 前一個字符0次或1次擴展 | abc*表示ab、abc |
| | 左右表達式任意一個 | abc|def表示abc、def |
{m} | 擴展前一個字符m次 | ab{2}c表示abbc |
{m,n} | 擴展前一個字符m至n次(含n) | ab{1,2}c表示abc,abbc |
^ | 匹配字符串開頭 | abc且在一個字符串的開頭 |
$ | 匹配字符串結尾 | abc且在一個字符串的結尾 |
() | 分組標記,內部只能使用|操作符 | (abc)表示abc,(abc|def)表示abc、def |
\d | 數字,等價於[0-9] | |
\w | 單詞字符,等價於[A-Za-z0-9_] |
語法實例
正則表達式 | 對應字符串 |
P(Y|YT|YTH|YTHO)?N | ‘PN’、’PYN’、’PYTN’、’PYTHN’、’PYTHON’ |
PYTHON+ | ‘PYTHON’、’PYTHONN’、’PYTHONNN’…… |
PY[TH]ON | ‘PYTON’、’PYHON’ |
PY[^TH]?ON | ‘PYON’、’PYaON’、’PYbON’、’PYcON’…… |
PY{:3}ON | ‘PN’、’PYN’、’PYYN’、’PYYYN’ |
經典實例
正則表達式 | 意義 |
^[A-Za-z]+$ | 由26個字母組成的字符串 |
^[A-Za-z0-9]+$ | 由26個字母和數字組成的字符串 |
^-?\d+$ | 整數形式的字符串 |
^ [1-9]*[0-9]*$ | 正整數形式的字符串 |
[1-9]\d{5} | 中國境內郵政編碼,6位 |
[\u4e00-\u9fa5] | 匹配中文字符 |
\d{3}-\d{8}|\d{4}-\d{7} | 國內電話號碼 3位-8位或4位-7位 |
二、Re庫
Re庫是Python的標准庫,主要用於字符串匹配,調用方法“import re”
1、正則表達式的類型
Re庫采用raw string(原生字符串類型)表達正則表達式,表示為r'text',raw string是不包含轉義符的字符串
如 r'[1-9]\d{5}'、r'\d{3}-\d{8}|\d{4}-\d{7}'
string類型更繁瑣,需要對一些特殊符號進行轉義
如 '[1-9]\\d{5}'、'\\d{3}-\\d{8}|\\d{4}-\\d{7}'
2、Re庫的主要功能函數
函數 | 說明 |
re.search() | 從一個字符串中搜索匹配正則表達式的第一個位置,返回match對象 |
re.match() | 從一個字符串的開始位置起匹配正則表達式,返回match對象 |
re.findall() | 搜索字符串,以列表類型返回全部能匹配的子串 |
re.split() | 將一個字符串按照正則表達式匹配結果進行分割,返回列表類型 |
re.finditer() | 搜索字符串,返回一個匹配結果的迭代類型,每個迭代元素是match對象 |
re.sub() | 在一個字符串中替換所有匹配正則表達式的子串,返回替換后的字符串 |
(1)re.search()函數
re.search(pattern,string,flags = 0)
在一個字符串中搜索匹配正則表達式的第一個位置,返回match對象
pattern:正則表達式的字符串或原生字符串表示
string:待匹配字符串
flags:正則表達式使用時的控制標記
1 import re 2 match = re.search(r'[1-9]\d{5}','BIT 100081') 3 if match: 4 print(match.group(0)) 5 100081
常用標記 | 說明 |
re.I re.IGNORECASE | 忽略正則表達式的大小寫,[A-Z]能夠匹配小寫字符 |
re.M re.MULTILINE | 正則表達式中^操作符能夠將給定字符串的每行當做匹配開始 |
re.S re.DOTALL | 正則表達式中的.操作符能夠匹配所有字符,默認匹配除換行外的所有字符 |
(2)re.match()函數
re.match(pattern,string,flags = 0)
從一個字符串的開始位置起匹配正則表達式,返回match對象
pattern:正則表達式的字符串或原生字符串表示
string:待匹配字符串
flags:正則表達式使用時的控制標記
1 import re 2 match = re.match(r'[1-9]\d{5}','BIT 100081') 3 if match: 4 print(match.group(0)) 5 6 match.group(0) 7 Traceback (most recent call last): 8 File "<input>", line 1, in <module> 9 AttributeError: 'NoneType' object has no attribute 'group'
由以上代碼可看出,匹配不出以'BIT'開頭的字符串,調用match.group(0)返回為空
1 import re 2 match = re.match(r'[1-9]\d{5}','100081 BIT') 3 if match: 4 print(match.group(0)) 5 100081
(3)re.findall()函數
re.findall(pattern,string,flags = 0)
搜索字符串,以列表類型返回全部能匹配的子串
pattern:正則表達式的字符串或原生字符串表示
string:待匹配字符串
flags:正則表達式使用時的控制標記
1 import re 2 ls = re.findall(r'[1-9]\d{5}','BIT100081 TSU100084') 3 ls 4 ['100081', '100084']
(4)re.split()函數
re.split(pattern,string,maxsplit = 0,flags = 0)
將一個字符串按照正則表達式匹配結果進行分割,返回列表類型
pattern:正則表達式的字符串或原生字符串表示
string:待匹配字符串
maxsplit:最大分割數,剩余部分作為最后一個元素輸出
flags:正則表達式使用時的控制標記
1 import re 2 re.split(r'[1-9]\d{5}','BIT100081 TSU100084') 3 ['BIT', ' TSU', ''] #將匹配的字符串去掉,剩余分割部分放入一個列表 4 re.split(r'[1-9]\d{5}','BIT100081 TSU100084',maxsplit = 1) 5 ['BIT', ' TSU100084'] #將匹配的第一個字符串去掉,剩余分割部分放入一個列表(匹配的第一個字符串后的所有部分作為一個整體)
(5)re.finditer()函數
re.finditer(pattern,string,flags = 0)
搜索字符串,返回一個匹配結果的迭代類型,每個迭代元素是match對象
pattern:正則表達式的字符串或原生字符串表示
string:待匹配字符串
flags:正則表達式使用時的控制標記
1 import re 2 for m in re.finditer(r'[1-9]\d{5}','BIT100081 TSU100084'): 3 if m: 4 print(m.group(0)) 5 100081 6 100084
(6)re.sup()函數
re.sup(pattern,repl,string,count = 0,flags = 0)
在一個字符串中替換所有匹配正則表達式的子串,返回替換后的字符串
pattern:正則表達式的字符串或原生字符串表示
repl:替換匹配字符串的字符串
string:待匹配字符串
count:匹配的最大替換次數
flags:正則表達式使用時的控制標記
1 import re 2 re.sub(r'[1-9]\d{5}','zipcode','BIT100081 TSU100084') 3 'BITzipcode TSUzipcode'
3、Re庫的用法
(1)函數式用法:一次性操作
1 rst = re.search(r’[1-9]\d{5}’,’BIT 100081’)
(2)面向對象用法:編譯后的多次操作
1 pat = re.compile(r’[1-9]\d{5}’) 2 rst = pat.search(‘BIT 100081’)
(3)re.compile()函數
regex = re.compile(pattern,flags = 0)
將正則表達式的字符串形式編譯成正則表達式對象
pattern:正則表達式的字符串或原生字符串表示
flags:正則表達式使用時的控制標記
經過re.compile()方法后,regex被編譯為正則表達式對象,可以使用對象方法,即regex.search()、regex.match()、regex.findall()、regex.split()、regex.finditer()、regex.sub()
1 import re 2 regex = re.compile(r'[1-9]\d{5}') 3 regex.search('100081') 4 <re.Match object; span=(0, 6), match='100081'> 5 regex.search('100081').group(0) 6 '100081'
4、Match對象
(1)Match的屬性
屬性 | 說明 |
.string | 待匹配的文本 |
.re | 匹配時使用的pattern對象(正則表達式) |
.pos | 正則表達式搜索文本的開始位置 |
.endpos | 正則表達式搜索文本的結束位置 |
1 import re 2 m = re.search(r'[1-9]\d{5}','BIT100081 TSU100084') 3 m.string #待匹配的字符串 4 'BIT100081 TSU100084' 5 m.re #匹配時使用的正則表達式 6 re.compile('[1-9]\\d{5}') 7 m.pos #正則表達式搜索文本的開始位置 8 0 9 m.endpos #正則表達式搜索文本的結束位置 10 19
(2)Match的方法
方法 | 說明 |
.group(0) | 獲得匹配后的字符串 |
.start() | 匹配字符串在原始字符串的開始位置 |
.end() | 匹配字符串在原始字符串的結束位置 |
.span() | 返回(.start(),.end()) |
1 import re 2 m = re.search(r'[1-9]\d{5}','BIT100081 TSU100084') 3 m.group(0) #獲得匹配后的字符串 4 '100081' #返回第一次匹配的結果 5 m.start() #匹配字符串在原始字符串的開始位置 6 3 7 m.end() #匹配字符串在原始字符串的結束位置 8 9 9 m.span() #返回(.start(),.end()) 10 (3, 9)
5、貪婪匹配和最小匹配
(1)貪婪匹配
貪婪匹配即匹配最長的子串,Re庫默認采用貪婪匹配
1 import re 2 match = re.search(r'PY.*N','PYANBNCNDN') 3 match.group(0) 4 'PYANBNCNDN'
(2)最小匹配
最小匹配即匹配最短的子串
操作符 | 說明 |
*? | 前一個字符0次或無限次擴展,最小匹配 |
+? | 前一個字符1次或無限次擴展,最小匹配 |
?? | 前一個字符0次或1次擴展,最小匹配 |
{m,n}? | 擴展前一個字符m至n次(含n),最小匹配 |
1 import re 2 match = re.search(r'PY.*?N','PYANBNCNDN') #最小匹配 3 match.group(0) 4 'PYAN'
資料來源:《Python網絡爬蟲與信息提取》——嵩天,北京理工大學,MOOC