1. 程式人生 > >(數據科學學習手劄32)Python中re模塊的詳細介紹

(數據科學學習手劄32)Python中re模塊的詳細介紹

簡介 print 兩種 clas 就是 HERE 每次 str 通過

一、簡介

  關於正則表達式,我在前一篇(數據科學學習手劄31)中已經做了詳細介紹,本篇將對Python中自帶模塊re的常用功能進行總結;

  re作為Python中專為正則表達式相關功能做出支持的模塊,提供了一系列方法來完成幾乎全部類型的文本信息的處理工作,下面一一介紹:

二、re.compile()

  在前一篇文章中我們使用過這個方法,它通過編譯正則表達式參數,來返回一個目標對象的匹配模式,進而提高了正則表達式的效率,主要參數如下:

pattern:輸入的欲編譯正則表達式,需將正則表達式包裹在‘‘內傳入,如‘aa*’

flags:編譯標誌位,用於從某個角度修改正則表達式的匹配方式,常用的有:

  re.S:使.匹配包括換行在內的所有字符

  re.I:使匹配對大小寫不敏感

  re.U:根據Unicode規則解析字符,主要用於對中文的匹配中

下面是幾個簡單的例子:

import re

text = 即使你沒聽說過“維基百科六度分隔理論”,也很可能聽過“凱文 · 貝肯(Kevin Bacon)的六度分隔值遊戲”。在這兩個遊戲中,都是把兩個不相幹的主題(維基百科裏是用詞條之間的連接,凱文 · 貝肯的六度分隔值遊戲是用出現在同一部電影中的演員來連接)用一個總數不超過六條的主題連接起來(包括原來的兩個主題)。

‘‘‘編譯我們的正則表達式,規則為找到所有在雙引號內的內容(不包括雙引號)
‘‘‘ regex = re.compile(“(.*?)”) ‘‘‘打印匹配結果‘‘‘ print(regex.findall(text))

運行結果:

技術分享圖片

可以看出,匹配到的所有內容會以列表的形式返回;

import re

text = 即使你沒聽說過“維基百科六度分隔理論”,也很可能聽過“凱文 · 貝肯(Kevin Bacon)的六度分隔值遊戲”。在這兩個遊戲中,都是把兩個不相幹的主題(維基百科裏是用詞條之間的連接,凱文 · 貝肯的六度分隔值遊戲是用出現在同一部電影中的演員來連接)用一個總數不超過六條的主題連接起來(包括原來的兩個主題)。

‘‘‘編譯我們的正則表達式,規則為大小寫英文字母至少出現一次的內容
‘‘‘ regex = re.compile([A-Za-z]+) ‘‘‘打印匹配結果‘‘‘ print(regex.findall(text))

運行結果:

技術分享圖片

接下來我們對flags參數進行賦值,看看會實現怎樣的功能:

import re

text = 即使你沒聽說過“維基百科六度分隔理論”,也很可能聽過“凱文 · 貝肯(Kevin Bacon)的六度分隔值遊戲”。在這兩個遊戲中,都是把兩個不相幹的主題(維基百科裏是用詞條之間的連接,凱文 · 貝肯的六度分隔值遊戲是用出現在同一部電影中的演員來連接)用一個總數不超過六條的主題連接起來(包括原來的兩個主題)。

‘‘‘編譯我們的正則表達式,規則為小寫英文字母至少出現一次的內容‘‘‘
regex = re.compile([a-z]+)#未使用flags無視大小寫

‘‘‘打印匹配結果‘‘‘
print(regex.findall(text))

運行結果:

技術分享圖片

因為我們使用的正則表達式為[a-z]+,所以大寫字母部分未能匹配到,下面我們不改變我們的正則表達式部分,而是對flags進行賦參:

import re

text = 即使你沒聽說過“維基百科六度分隔理論”,也很可能聽過“凱文 · 貝肯(Kevin Bacon)的六度分隔值遊戲”。在這兩個遊戲中,都是把兩個不相幹的主題(維基百科裏是用詞條之間的連接,凱文 · 貝肯的六度分隔值遊戲是用出現在同一部電影中的演員來連接)用一個總數不超過六條的主題連接起來(包括原來的兩個主題)。

‘‘‘編譯我們的正則表達式,規則為小寫英文字母至少出現一次的內容‘‘‘
regex = re.compile([a-z]+,flags=re.I)#使用re.I無視大小寫

‘‘‘打印匹配結果‘‘‘
print(regex.findall(text))

運行結果:

技術分享圖片

在使用flags=re.I來無視大小寫的情況下,在原有的正則表達式的基礎上,實現了對大寫字母的匹配。

三、re.match()

  這個方法個人覺得用的是不是很多,它表示以定義的正則表達式作為對目標字符串開頭的匹配(對非開頭部分不匹配),下面是一個簡單的例子:

import re

text = What are you waiting for?

‘‘‘成功匹配到開頭,因為字符串開頭是W‘‘‘
print(re.match(w,text,re.I).group())

運行結果:

技術分享圖片

當字符串開頭不匹配時,即使字符串其他部分有匹配的也不返回值(即所謂的只匹配開頭部分):

import re

text = What are you waiting for? where are you fucking from?

‘‘‘未能成功匹配到開頭,因為字符串開頭是Wha‘‘‘
print(re.match(whe,text,re.I))

運行結果:

技術分享圖片

四、re.search()

  re.search()的使用格式類似re.match(),即三個傳入參數:pattern,string,flags,但與match匹配開頭不同的是,search匹配的是文中出現的第一個滿足條件的字符串部分並返回,對後續的不再進行匹配,下面是一個簡單的例子:

import re

text = What are you waiting for? where are you fucking from?

‘‘‘成功匹配到第一個出現的目標內容,後續的內容便不再匹配‘‘‘
print(re.search(a,text,re.I).group())

運行結果:

技術分享圖片

文中有很多a,但search遇到第一個a便停止匹配並返回這第一個值;

這裏要註意一下,我在前面幾個例子中使用到的group()方法,是針對match或search成功匹配並返回的對象,我們稱之為match object,圍繞它的常用方法如下:

  strat():返回匹配開始的位置

  end():返回匹配結束的位置

  group():返回被re匹配的字符串

  span():返回一個tuple格式的對象,標記了匹配開始,結束的位置,形如(start,end)

事實上,雖然說search只返回一個對象,但我們可以通過將正則表達式改造成若幹子表達式拼接的形式,來返回多個分塊的對象

import re

text = 1213sdsdjAKNNK

‘‘‘匹配復合表達式對應的內容(返回對象會根據子表達式進行分塊),並分別打印第1、2、3塊子內容‘‘‘
print(re.search(([1-9]+)*([a-z]+)*([A-Z]+),text).group(1))
print(re.search(([1-9]+)*([a-z]+)*([A-Z]+),text).group(2))
print(re.search(([1-9]+)*([a-z]+)*([A-Z]+),text).group(3))

運行結果:

技術分享圖片

五、findall()

  註意,這和我們在解析BeautifulSoup對象時使用到的findAll()拼寫不同(雖然功能相似),它與match和search不同的是,它會根據傳入的正則表達式部分來提取目標字符串中所有符合規則的部分,並傳出為列表的形式,下面是一個簡單的例子:

import re

text = 即使你沒聽說過“維基百科六度分隔理論”,也很可能聽過“凱文 · 貝肯(Kevin Bacon)的六度分隔值遊戲”。在這兩個遊戲中,都是把兩個不相幹的主題(維基百科裏是用詞條之間的連接,凱文 · 貝肯的六度分隔值遊戲是用出現在同一部電影中的演員來連接)用一個總數不超過六條的主題連接起來(包括原來的兩個主題)。

‘‘‘匹配text中所有以 聽 開頭的長度為2的字符串‘‘‘
print(re.findall(聽.,text))

運行結果:

技術分享圖片

與前面在介紹re.compile()時對findall的用法不同,這裏是re.findall(正則表達式,目標字符串)的格式,前面的是 編譯好的正則模式.findall(目標字符串),這兩種格式的功能等價;

六、re.finditer()

  我們有時候會遇到這樣的情況:目標字符串非常長(可能是一整篇小說),而符合我們正則表達式的目標內容也非常的多,這種時候如果沿用前面的做法使用re.findall()來一口氣將所有結果提取出來保存在一個碩大的列表中,是件非常占用內存的事情,而Python中用來節省內存的生成器(generator)就派上了用場;

  re.finditer(pattern,string,flags=0)就利用了這種機制,它構造出一個基於正則表達式pattern和目標字符串string的生成器,使得我們可以在對該生成器的循環中邊循環邊計算對應位置的值,即從始至終每一輪只保存了當前的位置和當前匹配到的內容,達到節省內存的作用,下面是一個簡單的例子:

import re

text = abjijdianbdadjijijiha8hihanihhhiihiaaihidaihihaidhihaidahi

‘‘‘構造我們的叠代器‘‘‘
obj = re.finditer(a.,text)

‘‘‘對obj進行叠代,每次返回當前位置匹配到的內容及對應的起始與結束位置‘‘‘
for i in obj:
    print(i.group())
    print(i.span())

運行結果:

技術分享圖片

七、re.sub()

  類似字符串操作中的replace(),只不過replace()中只能死板地設置固定的內容作為替換項,利用re.sub(pattern,repl,string,count)則可以基於正則表達式達到靈活匹配替換內容,pattern指定了正則表達式部分,repl指定了進行替換的新內容,string指定目標字符串,count指定了替換的次數,默認全部替換,其實前一篇文章結尾處我們得到一篇幹凈的新聞報道就用到了這種方法,下面再舉一個簡單的例子:

import re

text = abjijdianbdadjijijiha8hihanihhhiihiaaihidaihihaidhihaidahi

‘‘‘構造我們的替代規則‘‘‘
obj = re.sub(a.,嘻嘻,text)

‘‘‘打印替換後內容‘‘‘
print(obj)

運行結果:

技術分享圖片

八、re.split()

  類似於字符串處理中的split(),re.split()在原有基礎上擴充了正則表達式的功能,re.split(pattern,string,maxsplit),其中pattern指定分隔符的正則表達式,string指定目標字符串,maxsplit指定最大分割個數,下面是一個簡單的例子:

import re

text = abjijdianbdadjijijiha8hihanihhhiihiaaihidaihihaidhihaidahi

‘‘‘構造我們的分割規則‘‘‘
obj = re.split(i.,text)

‘‘‘打印分割後內容‘‘‘
print(obj)

運行結果:

技術分享圖片

  

  以上就是關於re模塊的常用功能,接下來會以一篇實戰來詳細介紹實際業務中的網絡數據采集過程。

(數據科學學習手劄32)Python中re模塊的詳細介紹