CDA數據分析師 出品
數據分析工作中很多任務是跟文本處理相關,比如從文本中提取客戶的信息,從文本中提取時間等等都是比較常見的操作。 雖然Python處理字符串的方法很多,而且流行的pandas庫也提供了大量的向量化字符串方法,但是一旦涉及要經過較為複雜的數據匹配才能進行的字符操作,這些方法就顯得非常的乏力。
尤其是由於文本數據來源於爬蟲等渠道,數據往往嚴重不規整,這時候文本處理起來就顯得尤為吃力。
幸運的是Python提供了re模塊,可以實現正則表達式的操作。re模塊主要通過六大方法來對字符串進行處理,包括:match()、search()、findall()、split()、sub()。
這些方法涉及到字符串的匹配與替換等操作,在接下來的4篇連載文章裡,我們不單只會講解這4種方法,還會把元字符、行定位符、限定符、字符類、排除字符、選擇字符、轉義字符、分組等正則表達式最常用知識點貫穿起來。
接下來的系列文章將會為大家初步搭建較為完整的Python正則表達式知識體系,如果你已經學習完Python編程基礎和數據清洗的課程知識,該系列文章將會讓你對使用Python正則表達式達到一學就會,一用就懂的技能熟悉程度,實現真正的融會貫通的目的。
re.match方法
我們首先看re模塊中較為簡單的match()方法。
match 的作用是利用 Pattern 實例,從字符串左側開始匹配,如果匹配到就返回一個 Match 實例,如果第一個字符不符合條件,就返回 None。其語法格式如下:
re.match(pattern,string,[flags])
· pattern:表示模式字符串,由要匹配的正則表達式轉換而來。
· string:表示要匹配的字符串。
· flags:可選參數,表示標誌位,這個參數我們後續再講。
模式字符串是什麼意思呢?先看以下例子:
pattern='企業名稱'
message='企業名稱:CDA數據科學研究院'
match = re.match(pattern, message)
match
Out:<re.Match object; span=(0, 4), match='企業名稱'>
這時我們發現,re.match()方法返回了一個re.match對象,但這對象裡面的信息什麼意思呢?
在上面的例子中,我們的模式字符串沒有使用任何其他特殊字符,只是"企業名稱"。
而字符串message前面幾個字符串剛好是"企業名稱",因此返回來的re.match對象可以解讀出以下信息:
· "企業名字"這幾個字符串能在message中索引區間span(0,4)中匹配上
· 匹配結果就是match='企業名稱'
另外,re.match對象還可以通過調用.start()方法以及.end()來獲取匹配值的開始和結束位置:
match.start()
match.end()
也可以通過.span()方法獲得記載匹配字符所處位置索引的元組:
match.span()
Out: (0, 4)
在message中被匹配上的字符串可以通過.group()方法獲得:
match.group()
Out:'企業名稱'
被匹配的字符串可以通過re.match對象的string屬性來調用:
match.string
Out:'企業名稱:CDA數據科學研究院'
re.search方法
如果說,要匹配字符串並非出現在message的開頭,而是中間,match()方法就沒辦法匹配上了,這時候可以使用re.search()方法。
比如我們想要匹配message中的"CDA數據科學院研究院",我們將pattern指向對象改成"企業名稱",調用re.search()方法即可:
pattern='CDA數據科學研究院'
message='企業名稱:CDA數據科學研究院'
search = re.search(pattern, message)
search
Out:<re.Match object; span=(5, 15), match='CDA數據科學研究院'>
值得注意的是,re.search()方法結果返回的也是re.match對象,因此前面提及到的該類對象的方法和屬性同樣可以調用。
search.start()
search.end()
search.span()
search.group()
search.string
Out:5
15
(5, 15)
'CDA數據科學研究院'
'企業名稱:CDA數據科學研究院'
元字符
好,我們繼續思考,如果我們想要將message中"CDA"後面的一個字符也匹配上,pattern該如何寫?
pattern='CDA.'
message='企業名稱:CDA數據科學研究院\n郵箱:1918560461@qq.com'
search = re.search(pattern, message)
search
Out:<re.Match object; span=(5, 9), match='CDA數'>
通過上面的例子我們會發現,message中字符串"CDA"後面的"數"字也匹配上了,這只需要在設置pattern的時候,在字符串"CDA"後面多加一個圓點,而這圓點的作用就是可以幫你匹配除了換行符以外的任意字符。
除此之外,我們還可以把圓點換成"\w",最終效果也是一樣的:
pattern='CDA\w'
message='企業名稱:CDA數據科學研究院\n郵箱:1918560461@qq.com'
search = re.search(pattern, message)
search
Out:<re.Match object; span=(5, 9), match='CDA數'>
"\w"的作用就是可以幫你匹配字符、數字、下劃線或者是漢字。
而這些符號叫做元字符。
除了圓點和"\w"以外,還有以下元字符:
這裡需要注意的是,由於元字符大多數都包含特殊字符和反斜槓,因此,為了匹配原生字符串,可以在元字符之前添加r或R,如:
pattern=r'\bCDA.{5}' # 在元字符之前添加r
message='企業名稱:經管之家CDA數據科學研究院 CDA數據分析師\n郵箱:1918560461@qq.com'
search = re.search(pattern, message)
print(search)
Out:<re.Match object; span=(20, 28), match='CDA數據分析師'>
在上面的例子中,我們還需要注意的就是,由於模式字符串中帶有元字符"\b",而"\b"會匹配分界符(空格,標點符號或換行符)。
因此messgae中左邊起第一個"CDA"字符串前面由於沒有分界符,最終匹配的是第二個"CDA"字符串。
那麼上面模式字符串中出現的花括號"{}"是什麼意思呢?這就是我們接下來要講解的限定符。
限定符
前面學習了元字符,我們配合re.match()方法和re.search()方法就可以進行非常靈活的字符匹配。
但是只有元字符還有很多地方無法解決,比如,我們希望匹配字符串'企業名稱:CDA數據科學研究院\n郵箱:1918560461@qq.com'中的郵箱,該怎麼辦?
這個時候,我們就可以在模式字符串中添加限定符:
pattern='郵箱:.{17}'
message='經管之家CDA數據科學研究院\n郵箱:1918560461@qq.com'
search = re.search(pattern, message)
print(search)
Out:<re.Match object; span=(15, 35), match='郵箱:1918560461@qq.com'>
上面的patrern參數設置的原理是:既然是要匹配出message中的郵箱信息,而郵箱信息是在messaage中字符串"郵箱:"的後面,如果郵箱信息的長度為1,pattern可以寫成"郵箱:.".
但是該郵箱信息長度為17個字符,也就是說,要匹配message中"郵箱:"後面的17個字符,這時在上面的pattern後面添加限定符"{17}"就可以匹配17個字符(不包括換行符)。
但是如果郵箱信息長度不是為17,那該怎麼辦?由於郵件信息就是在message中字符串"郵箱:"的後面一直到末端,因此我們可以這樣寫:
pattern='郵箱:.*'
message='經管之家CDA數據科學研究院\n郵箱:1918560461@qq.com'
search = re.search(pattern, message)
print(search)
Out:<re.Match object; span=(15, 35), match='郵箱:1918560461@qq.com'>
除了上面提及的"{n}"和"*"以外,還有那些常用的限定符呢?
這裡需要給大家一個提醒的是,由於元字符"."是匹配除了換行符以外的任意字符,因此,即使我們的message中,郵箱信息後面如果有換行,上面的方法依然可以匹配出郵箱信息,比如:
pattern='郵箱:.*'
message='企業名稱:CDA數據科學研究院\n郵箱:1918560461@qq.com\n地址:北京市海澱區廠窪街3號2號樓2-3層\n網址:www.cda.cn'
search = re.search(pattern, message)
print(search)
Out:<re.Match object; span=(16, 36), match='郵箱:1918560461@qq.com'>
但是,如果上面的message中"地址"兩個字的前面沒有換行符"\n"呢?該如何匹配出郵箱信息?
我們只需要在pattern中星號的後面加上郵箱地址最後的字符"com"作為匹配的結束即可:
pattern='郵箱:.*com'
message='企業名稱:CDA數據科學研究院\n郵箱:1918560461@qq.com地址:北京市海澱區廠窪街3號2號樓2-3層\n網址:www.cda.cn'
search = re.search(pattern, message)
print(search)
Out:<re.Match object; span=(16, 36), match='郵箱:1918560461@qq.com'>