「Python標(biāo)準(zhǔn)庫:re」如何在Python中使用正則表達(dá)式

Python的正則表達(dá)式

Python通過導(dǎo)入標(biāo)準(zhǔn)庫re實(shí)現(xiàn)正則表達(dá)式(regular expression)茂装,Python的正則表達(dá)式引擎和Perl一樣驳阎,并且兼容Perl流派的元字符仿村。

元字符

Python支持的元字符很多间学,一種是比較常見入偷,我之前也就只會(huì)用這些

  • .表示任意一個(gè)字符,默認(rèn)不匹配換行符眉枕,制表符
  • |表示或恶复,ca|bd會(huì)匹配ca或bd,而不是cab, cbd, 如果想要匹配后者,則需要用到()進(jìn)行分組
  • ^,$表示位置符號(hào)速挑,行首和行尾 如^ab$匹配ab, 不匹配eab, abe,aeb
  • 量詞寂玲,表示重復(fù)數(shù),*任意多次, +一次以上, ?0次或一次, {m,n}m~n次, {m}重復(fù)m次,{m,}重復(fù)大于m次
  • 在上述量詞后接?, 就從貪婪模式變?yōu)榉秦澙纺J焦R Ee個(gè)例子,對(duì)于abbbbbb這個(gè)字符串想许,ab*ab*?的結(jié)果不同伶授,前者匹配abbbbbb,后者匹配a流纹,也就是貪婪模式盡可能多匹配糜烹。
  • [...]表示多選項(xiàng),比如a[bc]就可以匹配ab,ac, 如果是[a-z]那么表示從a到z范圍. 所有元字符在[]中都會(huì)被認(rèn)為是普通字符漱凝。所有元字符在[]
  • (...)表示捕獲型分組疮蹦,被(...)匹配到部分,可以用\1,\2進(jìn)行引用
  • "" 表示轉(zhuǎn)義茸炒,由于該符號(hào)也是字符串的元字符愕乎,那么在構(gòu)建模式的時(shí)候要萬分小心阵苇,因?yàn)镻ython會(huì)先對(duì)字符串進(jìn)行加工,然后才會(huì)傳入到正則引擎中感论。也就是說绅项,也就是如果你想匹配"" , 你的模式寫法得是\\\\,因?yàn)槿绻粚?code>\\,會(huì)被Python先翻譯成\,所以必須寫成\\\\比肄。因此建議用使用原始字符串(raw string),即r"\\"

下面的一些比較高級(jí)快耿,在我寫作時(shí)能記得的元字符,基本上都是(?...)一類的增強(qiáng)型標(biāo)記芳绩,具體含義和?后緊接的第一個(gè)字符有關(guān)

  • (?:...): 非捕獲型分組掀亥,也就是僅僅分組,正則引擎不會(huì)記住他用于后續(xù)引用
  • (?=...): 向后檢查妥色,要求當(dāng)前位置后符合...表示的模式, (?!...)也是向后檢查搪花,只不過要求當(dāng)前位置緊接的內(nèi)容不能被...匹配
  • (?<=...)(?<!...)是向前檢查。

在《精通正則表達(dá)式》中垛膝,作者舉了一個(gè)例子鳍侣,將"12345679"變?yōu)楦菀组喿x的"12,345,679"形式。 也就是找到一個(gè)位置前面是數(shù)字吼拥,后面是3的倍數(shù)個(gè)數(shù)字的位置插入逗號(hào)

re.sub(r"(?<=\d)(?=(\d\d\d)+$)",",","1234567")

下面是我需要翻閱資料才能記得

  • (?P<name>...): 在之前捕獲型括號(hào)的基礎(chǔ)上倚聚,將捕獲到的內(nèi)容賦值給name, 其中該內(nèi)容可以用(?P=name)進(jìn)行引用
  • (?#...): 這個(gè)僅僅是注釋,不做任意匹配
  • (?aiLmsux)比較復(fù)雜凿可,記不太起來
  • (?(id/name)yes-pattern|no-pattern)更加復(fù)雜揣非,需要舉一個(gè)例子宛琅。(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)來解釋,當(dāng)然這個(gè)例子理解起來也不容易。解釋起來就是锋勺,第一個(gè)括號(hào)先嘗試捕獲匹配<, 編號(hào)為1,然后是第二個(gè)括號(hào)匹配“字符串@字符串”叨粘,比如說user@host,然后第三個(gè)括號(hào)表示不捕獲分組, 識(shí)別".com"這類晤揣,然后第四個(gè)括號(hào)就是看第一個(gè)括號(hào)有沒有捕獲到東西,如果有就去匹配>纳击,沒有則是匹配行尾续扔。也就是你的郵箱地址要么為"user@host.com",要么為<user@host.com>,其他都是不符合要求。

常用函數(shù)

一般用法都是用re.compile構(gòu)建一個(gè)正則表達(dá)式對(duì)象焕数,這個(gè)正則表達(dá)式對(duì)象可以用在re.match,re.search,re.find,re.findall等函數(shù)里纱昧,同時(shí)該對(duì)象也有.match,.search方法。舉個(gè)例子堡赔,比如說你知道了一個(gè)形如GSExxx的GEO編號(hào)识脆,你需要提取這個(gè)編號(hào)下的所有GSMxxx編號(hào),然后根據(jù)這個(gè)GSMxxx編號(hào)去提取SRA編號(hào),以隨便找的GSE100566為例灼捂。

首先利用Python的requests庫抓取網(wǎng)頁信息

# Python
import re
import requests
base_url = "https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc="
acc      = "GSE101571"

resp = requests.get(base_url + acc)
contents = resp.text()

然后構(gòu)建一個(gè)正則表達(dá)式离例,去捕獲所有的GSMxxx類型的編號(hào)

pattern = "GSM\d+"
GSM_acc = re.findall(pattern, contents)

或許你不滿足于此,你還希望捕獲到每個(gè)GSM編號(hào)后的描述纵东,也就是"GSM2686880 SET-2_STAT1-D1",這兩個(gè)部分你都需要粘招。通過檢查網(wǎng)頁元素,你發(fā)現(xiàn)了一個(gè)規(guī)律偎球,也就是這兩個(gè)元素是在一個(gè)tr內(nèi)

HTML結(jié)構(gòu)

你信心滿滿的構(gòu)建了一個(gè)匹配模式洒扎,結(jié)果啥都沒有匹配到

pattern = re.compile("<tr><td.*?><a.*?>(GSM\d+)</a></td><td.*?>(.*?)</td>")
re.search(pattern, contents)

你發(fā)現(xiàn)這似乎由于這個(gè)HTML里有很多神奇的空白和"\n",原本方便人類閱讀的記號(hào)卻阻礙了數(shù)據(jù)處理,你必須做點(diǎn)什么衰絮,你想到了可以用re.sub進(jìn)行替換袍冷,所以你做了如下的事情

contents = re.sub(r"\n\s*","",contents)

最后你終于用原來的匹配模式得到了以元組數(shù)據(jù)結(jié)構(gòu)的結(jié)果

result = re.findall(pattern, contents)

下一步根據(jù)GSMxxx編號(hào)去提取SRX編碼。這一步的核心就是從元祖中提取元素猫牡,然后構(gòu)建一個(gè)url去爬取新的網(wǎng)頁胡诗,然后提取SRX編號(hào)即可以。先測(cè)試第一個(gè)淌友,

r1 = results[0][0]
r1_resp = requests.get(base_url + r1)
m = re.search("SRX\d+", r1_resp.text)
m.group(0)

然后開始遍歷,存儲(chǔ)到字典中煌恢。考慮到網(wǎng)絡(luò)延遲所耽誤的時(shí)間遠(yuǎn)遠(yuǎn)大于內(nèi)存分配的時(shí)間震庭,也就沒有必須要預(yù)先分配內(nèi)存空間瑰抵。

sra_dict = {}
for acc in results:
    key = acc[0]
    resp = requests.get(base_url + key)
    value = re.search("SRX\d+",resp.text).group(0)
    sra_dict[key] = value

事實(shí)證明網(wǎng)絡(luò)不好,這個(gè)簡單的程序是可以跑半天的器联。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末二汛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拨拓,更是在濱河造成了極大的恐慌肴颊,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渣磷,死亡現(xiàn)場離奇詭異婿着,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)醋界,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門祟身,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人物独,你說我怎么就攤上這事÷仍幔” “怎么了挡篓?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我官研,道長秽澳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任戏羽,我火速辦了婚禮担神,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘始花。我一直安慰自己妄讯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布酷宵。 她就那樣靜靜地躺著亥贸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浇垦。 梳的紋絲不亂的頭發(fā)上炕置,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音男韧,去河邊找鬼朴摊。 笑死,一個(gè)胖子當(dāng)著我的面吹牛此虑,可吹牛的內(nèi)容都是我干的甚纲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼寡壮,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼贩疙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起况既,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤这溅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后棒仍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悲靴,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年莫其,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了癞尚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乱陡,死狀恐怖浇揩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情憨颠,我是刑警寧澤胳徽,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布积锅,位于F島的核電站,受9級(jí)特大地震影響养盗,放射性物質(zhì)發(fā)生泄漏缚陷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一往核、第九天 我趴在偏房一處隱蔽的房頂上張望箫爷。 院中可真熱鬧,春花似錦聂儒、人聲如沸虎锚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翁都。三九已至,卻和暖如春谅猾,著一層夾襖步出監(jiān)牢的瞬間柄慰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來泰國打工税娜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坐搔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓敬矩,卻偏偏與公主長得像概行,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弧岳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355