通俗易懂的python正則表達(dá)式RE入門

使用 Python 模塊 re 實(shí)現(xiàn)解析小工具

孫 翎, 賀 皓, 和 張 晗

2011 年 4 月 12 日發(fā)布

概要

在開發(fā)過程中發(fā)現(xiàn),Python 模塊 re(Regular Expression)是一個(gè)很有價(jià)值并且非常強(qiáng)大的文本解析工具砚尽,因而想要分享一下此模塊的使用方法。

有這樣一個(gè)簡(jiǎn)單而有趣的實(shí)踐范例:對(duì)于喜歡追看美劇的年輕人,最新一集美劇的播出時(shí)間常常是一個(gè)讓人頭疼的問題,一個(gè)實(shí)時(shí)更新美劇播出時(shí)間表的小工具會(huì)很受歡迎。

本文通過以上這個(gè)實(shí)例豪嚎,描述如何抓獲 TV.com 網(wǎng)站上的文本信息,利用 Python 的 re 模塊進(jìn)行解析谈火,并將熱門美劇播出時(shí)間顯示在自己的網(wǎng)頁上侈询,希望能夠以?shī)蕵返姆绞胶芎玫慕忉?re 模塊的用法。

Python 正則表達(dá)式模塊 (re) 簡(jiǎn)介

Python 的 re 模塊(Regular Expression 正則表達(dá)式)提供各種正則表達(dá)式的匹配操作糯耍,和 Perl 腳本的正則表達(dá)式功能類似扔字,使用這一內(nèi)嵌于 Python 的語言工具,盡管不能滿足所有復(fù)雜的匹配情況温技,但足夠在絕大多數(shù)情況下能夠有效地實(shí)現(xiàn)對(duì)復(fù)雜字符串的分析并提取出相關(guān)信息革为。Python 會(huì)將正則表達(dá)式轉(zhuǎn)化為字節(jié)碼,利用 C 語言的匹配引擎進(jìn)行深度優(yōu)先的匹配舵鳞。

Python 正則表達(dá)式語法

正則表達(dá)式可以包含普通字符和特殊字符震檩,普通字符(比如數(shù)字或者字母)可以直接對(duì)目標(biāo)字符串進(jìn)行匹配,在本文中我們主要討論利用特殊字符來模糊匹配某一些字符串的方法蜓堕,比如'|'或者'('抛虏,使用這些特殊字符,正則表達(dá)式可以表示某一類的普通字符套才,或者是改變其周圍的正則表達(dá)式的含義迂猴。具體如表 2-1 所示:

表 1. 正則表達(dá)式語法 (真的是通俗易懂了~)?

關(guān)于*?, +?, ?? 這個(gè)部分的例子有些紕漏. <.*>是貪婪匹配, <.*?>是非貪婪匹配(最小匹配)

包含’ \ ’的特殊序列的意義如表 2-2:

表 2. 正則表達(dá)式特殊序列


Python re 的主要功能

Python 的 re 正則表達(dá)式模塊定義了一系列函數(shù),常量以及異常霜旧;同時(shí)错忱,正則表達(dá)式被編譯成‘ RegexObject ’實(shí)例,本身可以為不同的操作提供方法挂据。接下來簡(jiǎn)要介紹一下這些函數(shù)的功能和用法以清。

compile

re.compile(pattern[, flags])

把正則表達(dá)式的模式和標(biāo)識(shí)轉(zhuǎn)化成正則表達(dá)式對(duì)象,供 match() 和 search() 這兩個(gè)函數(shù)使用崎逃。

re 所定義的 flag 包括:

re.I 忽略大小寫

re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依賴于當(dāng)前環(huán)境

re.M 多行模式

re.S 即為’ . ’并且包括換行符在內(nèi)的任意字符(’ . ’不包括換行符)

re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依賴于 Unicode 字符屬性數(shù)據(jù)庫(kù)

re.X 為了增加可讀性掷倔,忽略空格和’ # ’后面的注釋

例:以下兩種用法結(jié)果相同:

A)

compiled_pattern = re.compile(pattern)

result = compiled_pattern.match(string)


B)

result = re.match(pattern, string)

search

re.search(pattern, string[, flags])

在字符串中查找匹配正則表達(dá)式模式的位置,返回 MatchObject 的實(shí)例个绍,如果沒有找到匹配的位置勒葱,則返回 None。

對(duì)于已編譯的正則表達(dá)式對(duì)象來說(re.RegexObject)巴柿,有以下 search 的方法:

search (string[, pos[, endpos]])

若 regex 是已編譯好的正則表達(dá)式對(duì)象凛虽,regex.search(string, 0, 50) 等同于 regex.search(string[:50], 0)。

具體示例如下广恢。

>>> pattern = re.compile("a")

>>> pattern.search("abcde")???? # Match at index 0

>>> pattern.search("abcde", 1)? # No match;

match

re.match(pattern, string[, flags])

判斷 pattern 是否在字符串開頭位置匹配凯旋。對(duì)于 RegexObject,有:

match(string[, pos[, endpos]])

match() 函數(shù)只在字符串的開始位置嘗試匹配正則表達(dá)式,也就是只報(bào)告從位置 0 開始的匹配情況至非,而 search() 函數(shù)是掃描整個(gè)字符串來查找匹配钠署。如果想要搜索整個(gè)字符串來尋找匹配,應(yīng)當(dāng)用 search()荒椭。

split

re.split(pattern, string[, maxsplit=0, flags=0])

此功能很常用谐鼎,可以將將字符串匹配正則表達(dá)式的部分割開并返回一個(gè)列表。對(duì) RegexObject趣惠,有函數(shù):

split(string[, maxsplit=0])

例如狸棍,利用上面章節(jié)中介紹的語法:

>>> re.split('\W+', 'test, test, test.')

['test', 'test', 'test', '']

>>> re.split('(\W+)', ' test, test, test.')

[' test ', ', ', ' test ', ', ', ' test ', '.', '']

>>> re.split('\W+', ' test, test, test.', 1)

[' test ', ' test, test.']

對(duì)于一個(gè)找不到匹配的字符串而言,split 不會(huì)對(duì)其作出分割味悄,如:

>>> re.split('a*', 'hello world')

['hello world']

findall

re.findall(pattern, string[, flags])

在字符串中找到正則表達(dá)式所匹配的所有子串隔缀,并組成一個(gè)列表返回。同樣 RegexObject 有:

findall(string[, pos[, endpos]])

示例如下:

#get all content enclosed with [], and return a list

>>> return_list = re.findall("(\[.*?\])",string)

finditer

re.finditer(pattern, string[, flags])

和 findall 類似傍菇,在字符串中找到正則表達(dá)式所匹配的所有子串猾瘸,并組成一個(gè)迭代器返回。同樣 RegexObject 有:

finditer(string[, pos[, endpos]])

sub

re.sub(pattern, repl, string[, count, flags])

在字符串 string 中找到匹配正則表達(dá)式 pattern 的所有子串丢习,用另一個(gè)字符串 repl 進(jìn)行替換牵触。如果沒有找到匹配 pattern 的串,則返回未被修改的 string咐低。Repl 既可以是字符串也可以是一個(gè)函數(shù)揽思。對(duì)于 RegexObject 有:

sub(repl, string[, count=0])

此語法的示例有:

>>> p = re.compile( '(one|two|three)')

>>> p.sub( 'num', 'one word two words three words')

'num word num words num words'

同樣可以用以下方法,并指定 count 為 1(只替換第一個(gè)):

>>> p.sub( 'num', ' one word two words three words', count=1)

' num word two words three words'

subn

re.subn(pattern, repl, string[, count, flags])

該函數(shù)的功能和 sub() 相同见擦,但它還返回新的字符串以及替換的次數(shù)钉汗。同樣 RegexObject 有:

subn(repl, string[, count=0])

實(shí)例分析 - 使用 re 模塊實(shí)現(xiàn)美劇時(shí)間表

這一章節(jié)將描述使用 re 模塊進(jìn)行文本解析并實(shí)現(xiàn)美劇播出時(shí)間表小工具的細(xì)節(jié)。我們會(huì)引用實(shí)際的代碼片段鲤屡,解釋在實(shí)際程序中损痰,應(yīng)當(dāng)如何使用 re 模塊實(shí)現(xiàn)文本解析的功能。

需求分析

為了將我們感興趣的信息全部提取出來渲染到一個(gè)單獨(dú)的頁面上酒来,我們選取 www.tv.com 的 html 作為數(shù)據(jù)源卢未,獲取到其 HTML 文本之后用正則表達(dá)式解析并獲得相關(guān)內(nèi)容。

請(qǐng)注意用正則表達(dá)式分析 HTML 或 XML 是痛苦的堰汉。隨處可見的變化使得寫出一個(gè)通用的正則表達(dá)式變得極為困難辽社,象這樣的任務(wù)使用專用的 HTML 或 XML 解析器更為適宜 ( 如 http://www.crummy.com/software/BeautifulSoup/, 值得一提的是翘鸭,這個(gè)解析器也是用 Python RE 實(shí)現(xiàn)的 )滴铅,為了演示 Python RE 的使用,本文全部使用正則表達(dá)式處理文本就乓。

實(shí)現(xiàn)步驟

因?yàn)榇斯ぞ叩淖詈蠼Y(jié)果會(huì)被呈現(xiàn)在一個(gè)網(wǎng)頁上汉匙,它的主要功能就是從上述的 html code 中提取出我們感興趣的 element, 并按照我們自己的對(duì)內(nèi)容的選擇重新生成一個(gè)個(gè)性化過的頁面譬淳,請(qǐng)參見附件查看我們將要解析的 html 文本。

通過檢視此 html 文件盹兢,我們需要提取的 html element 只有被 head 標(biāo)簽修飾的文檔信息元素,和被 div 標(biāo)簽修飾守伸,id 值為 episode_listing 的塊級(jí)區(qū)域绎秒。

下面對(duì)實(shí)現(xiàn)這部分功能的主要代碼進(jìn)行一些分析。

以只讀方式打開所需處理文本并讀入其內(nèi)容:

fh = open("~/vampire_episode.html", "r")

fh_str = fd.read()

讀取劇集標(biāo)題尼摹,使用正則表達(dá)式匹配以“”結(jié)束的元素见芹,注意此處使用非貪婪匹配以獲取首次匹配的內(nèi)容:

title = re.findall("", fds)

查看一下變量類型和內(nèi)容:

In [74]: type(title)

Out[74]:

In [75]: print title

-------> print(title)

['The Vampire Diaries Season 2 Episode Guide on TV.com']

讀取 html 文本中 id 值為 episode_listing 的 div 元素,注意由于此元素會(huì)跨越多行蠢涝,我們?cè)谡{(diào)用 findall 函數(shù)時(shí)需要指定 re.S 標(biāo)志玄呛,同樣使用非貪婪匹配:

此時(shí)我們已經(jīng)獲取到全部所需內(nèi)容,將他們寫入另一個(gè) html 文件:

'''

部分測(cè)試用的website失效. 且簡(jiǎn)書的語法規(guī)則對(duì)程序code支持不夠好. 跳過.

需要閱讀的可以查看:https://www.ibm.com/developerworks/cn/opensource/os-cn-pythonre/index.html

'''

小結(jié)

盡管對(duì)于 Python 正則表達(dá)式模塊(re)的語法和相關(guān)函數(shù)的描述并不全面和二,但文章以簡(jiǎn)潔的方式介紹了最常用的正則表達(dá)式語法和函數(shù)調(diào)用方法徘铝,關(guān)于更為復(fù)雜和深入的用法討論,讀者可以參考官方文檔惯吕。在之后的章節(jié)中惕它,本文直觀地通過網(wǎng)頁文本解析的實(shí)例,講解了美劇播出時(shí)間解析小工具的實(shí)現(xiàn)方法和步驟废登,希望最后的網(wǎng)站示例和演示結(jié)果能夠提供給這一模塊的功能學(xué)習(xí)提供一些有趣并有用的幫助淹魄。

相關(guān)主題

參考 Python 使用文檔中 RE 相關(guān)章節(jié)The Python Standard Library - Regular expression operations,查看 RE 語法使用細(xì)節(jié)堡距。

參看文章Regular Expressions Primer甲锡,了解更多 Python RE 的使用實(shí)例。

參看 developerWorks 中的文章可愛的 Python:Python 中的文本處理羽戒,了解使用 Python RE 進(jìn)行文本解析的實(shí)例缤沦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市易稠,隨后出現(xiàn)的幾起案子疚俱,更是在濱河造成了極大的恐慌,老刑警劉巖缩多,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呆奕,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡衬吆,警方通過查閱死者的電腦和手機(jī)梁钾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逊抡,“玉大人姆泻,你說我怎么就攤上這事零酪。” “怎么了拇勃?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵四苇,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我方咆,道長(zhǎng)月腋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任瓣赂,我火速辦了婚禮榆骚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘煌集。我一直安慰自己妓肢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布苫纤。 她就那樣靜靜地躺著碉钠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卷拘。 梳的紋絲不亂的頭發(fā)上放钦,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音恭金,去河邊找鬼操禀。 笑死,一個(gè)胖子當(dāng)著我的面吹牛横腿,可吹牛的內(nèi)容都是我干的颓屑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼耿焊,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼揪惦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起罗侯,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤器腋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后钩杰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纫塌,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年讲弄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了措左。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡避除,死狀恐怖怎披,靈堂內(nèi)的尸體忽然破棺而出胸嘁,到底是詐尸還是另有隱情,我是刑警寧澤凉逛,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布性宏,位于F島的核電站,受9級(jí)特大地震影響状飞,放射性物質(zhì)發(fā)生泄漏毫胜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一昔瞧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧菩佑,春花似錦自晰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瞧哟,卻和暖如春混巧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背勤揩。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工咧党, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人陨亡。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓傍衡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親负蠕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蛙埂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • re模塊手冊(cè) 本模塊提供了和Perl里的正則表達(dá)式類似的功能,不關(guān)是正則表達(dá)式本身還是被搜索的字符串遮糖,都可以...
    喜歡吃栗子閱讀 4,002評(píng)論 0 13
  • 本文介紹了Python對(duì)于正則表達(dá)式的支持绣的,包括正則表達(dá)式基礎(chǔ)以及Python正則表達(dá)式標(biāo)準(zhǔn)庫(kù)的完整介紹及使用示例...
    Python程序媛閱讀 1,348評(píng)論 0 22
  • 在前面我們已經(jīng)搞定了怎樣獲取頁面的內(nèi)容,不過還差一步欲账,這么多雜亂的代碼夾雜文字我們?cè)鯓影阉崛〕鰜碚砟芈沤肯旅婢烷_...
    知曰閱讀 4,209評(píng)論 1 15
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)赛不,斷路器盼理,智...
    卡卡羅2017閱讀 134,651評(píng)論 18 139
  • 給孩子一個(gè)好的教育,對(duì)孩子的成長(zhǎng)負(fù)責(zé)任俄删,關(guān)心孩子宏怔,愛護(hù)孩子奏路,是我們做父母的最大責(zé)任;望子成龍臊诊,望女成鳳鸽粉,都是...
    深優(yōu)U媽咪閱讀 257評(píng)論 0 0