正則表達式
什么是正則表達式
正則表達式是對字符串操作的一種邏輯公式纹烹,就是用事先定義好的一些特定字符、以及這些特定字符的組合,組成一個“規(guī)則字符串”泊愧,這個規(guī)則字符串用來表達對字符串的一種過濾邏輯
Python用re模塊實現(xiàn)
在線正則表達式工具
其中有許多常用的正則表達式,非常好用盛正。
一般的網(wǎng)頁可以用beautifulsoup等解析庫來提取删咱,不過有的網(wǎng)頁卸載js的變量中,只能使用正則表達式來提取豪筝。正則表達式可以用來篩選和清洗痰滋。非常有用摘能。
python中的正則表達式講解
-
常見匹配模式
模式 | 描述 |
---|---|
\w | 匹配字母數(shù)字及下劃線 |
\W | 匹配非字母數(shù)字下劃線 |
\s | 匹配任意空白字符、等價于[\t\n\r\f] |
\S | 匹配任意非空字符 |
\d | 匹配任意數(shù)字敲街,等價于[0-9] |
\D | 匹配任意非數(shù)字 |
\A | 匹配字符串的開始 |
\Z | 匹配字符串結(jié)束团搞,如果存在換行,只匹配到換行前的結(jié)束字符串 |
\z | 匹配字符串結(jié)束 |
\G | 匹配最后匹配完成的位置 |
\n | 匹配一個換行符 |
\t | 匹配一個制表符 |
^ | 匹配字符串的開頭 |
$ | 匹配字符串的結(jié)尾 |
. | 匹配任意字符多艇,除了換行符逻恐,當re.DOTALL標記被指定時,則可以匹配包括換行符的任意字符 |
[...] | 用來表示一組字符峻黍,單獨列出:[osi]匹配‘o’,'s','j' |
[^...] | 匹配除括號中內(nèi)容之外的字符 |
* | 匹配0個過多個表達式 |
+ | 匹配1個或多個表達式 |
复隆? | 匹配0個或者1個表達式 |
{n} | 精確匹配n個前面的表達式 |
{n,m} | 匹配n到m此有前面的正則表達式定義的片段,貪婪方式 |
a|b | 匹配a或b |
() | 匹配括號內(nèi)的表達式姆涩,也表示一個組 |
-
re.match
re.match 嘗試從字符串的起始位置匹配一個模式挽拂,如果不是起始位置匹配成功的話,match()就返回none阵面。
re.match(pattern,string,flags=0)
sample
1.常規(guī)的匹配
import re
content = 'Hello 3232 4324 World_This is a Regex Demo'
print(len(content))
result = re.match('^Hello\s\d{4}\s\d{4}\s\w{10}.*mo$',content)
print(result)
print(result.group())#匹配結(jié)果
print(result.span())#匹配結(jié)果在content中的范圍
2.泛匹配--用.* 表示任意字符
import re
content = 'Hello 3232 4324 World_This is a Regex Demo'
result = re.match('^Hello.*mo$',content)
print(result)
print(result.group())
print(result.span())
3.匹配目標
一般我們把匹配目標用小括號括起來轻局,然后指定左右端點,才能找到样刷。
import re
content = 'Hello 3232 4324 World_This is a Regex Demo'
result = re.match('^Hello\s(\d{4})\s(\d+)\s.*mo$',content)
print(result)
print(result.group(1))#第一個小括號括起來匹配的內(nèi)容
print(result.group(2))#第二個小括號括起來的內(nèi)容
print(result.span())
4.貪婪匹配
import re
content = 'Hello 3232 4324 World_This is a Regex Demo'
result = re.match('^He.*(\d+).*mo$',content)
print(result)
print(result.group(1))
print(result.span())
*結(jié)果是4仑扑,因為.*表示任意字符,默認貪婪模式會匹配盡量多的任意字符置鼻,而\d+至少要匹配一個數(shù)字镇饮,所以就一直匹配到最后一個數(shù)字之前。
5.非貪婪模式
import re
content = 'Hello 3232 4324 World_This is a Regex Demo'
result = re.match('^He.*?(\d+).*mo$',content)
print(result)
print(result.group(1))
print(result.span())
.*?是非貪婪模式箕母,匹配盡可能少字符储藐。
6.匹配模式
import re
content = "Hello 3232 4324 World_This \nis a Regex Demo\n"
result = re.match('^He.*?(\d+).*mo$',content)
print(result)
*結(jié)果為none,原因是.不能匹配換行符嘶是,修改之后可以匹配
import re
content = "Hello 3232 4324 World_This \nis a Regex Demo\n"
result = re.match('^He.*?(\d+).*mo$',content,re.S)
print(result)
添加re.S后即可
7.轉(zhuǎn)義
正則表達式中的許多特殊字符如果不做轉(zhuǎn)義就無法匹配钙勃,會被認為是關(guān)鍵字使用,比如*.[]等等聂喇。以下就是不轉(zhuǎn)義的例子
import re
content = 'price $50.09'
result = re.match('price $50.09',content)
print(result)
結(jié)果返回none辖源,沒匹配到。
轉(zhuǎn)義之后才能匹配
import re
content = 'price $50.09'
result = re.match('price \$50\.09',content)
print(result)
最常見用法總結(jié)希太,盡量使用泛匹配模式克饶,使用括號得到匹配目標,盡量使用非貪婪模式誊辉,使用re.S矾湃,因為HTML中有大量的換行符這樣.就能匹配任意字符了。
-
re.search
re.match從字符串的開頭匹配堕澄,比如pattern無法匹配content的第一個字符邀跃,那么直接返回none霉咨。而re.search會搜索整個字符串,只要搜索到符合pattern的內(nèi)容就返回第一個成功的匹配坞嘀。以下是sample躯护。
import re
content = "jlljjljh Hello 1234 World_This is a Regex Demo,Don't forget!$"
result = re.match('Hello.*?(\d+).*?',content)
print(result)#用match的話,result返回none
result = re.search('Hello.*?(\d+).*?',content)
print(result)#可以匹配
print(result.group(1))#返回1234
總結(jié)丽涩,盡量用re.search方法棺滞,盡量使用re.S,用非貪婪模式
練習(xí)
import re
html = '<div class="songList songList960 clearfix"><ol id="f1"><li><input type="checkbox" value="11417@" name="Url" class="check"> <span class="songNum topRed">01.</span> <a target="_1" href="/play/11417.htm" class="songName cBlue">大海</a></li><li><input type="checkbox" value="64541@" name="Url" class="check"> <span class="songNum topRed">02.</span> <a target="_1" href="/play/64541.htm" class="songName">天路</a></li><li><input type="checkbox" value="65937@" name="Url" class="check"> <span class="songNum topRed">03.</span> <a target="_1" href="/play/65937.htm" class="songName">再回首</a></li><li><input type="checkbox" value="59930@" name="Url" class="check"> <span class="songNum">04.</span> <a target="_1" href="/play/59930.htm" class="songName cBlue">突然的自我</a></li><li><input type="checkbox" value="1462@" name="Url" class="check"> <span class="songNum">05.</span> <a target="_1" href="/play/1462.htm" class="songName">甘心情愿</a></li></ol></div>'
result = re.search('songName.*?>(.*?)</a>.*',html,re.S)
print(result)
print(result.group(1))
匹配結(jié)果:大海
-
re.findall--搜索字符串矢渊,以列表形式返回全部能匹配的子串
import re
html = '<div class="songList songList960 clearfix"><ol id="f1"><li><input type="checkbox" value="11417@" name="Url" class="check"> <span class="songNum topRed">01.</span> <a target="_1" href="/play/11417.htm" class="songName cBlue">大海</a></li><li><input type="checkbox" value="64541@" name="Url" class="check"> <span class="songNum topRed">02.</span> <a target="_1" href="/play/64541.htm" class="songName">天路</a></li><li><input type="checkbox" value="65937@" name="Url" class="check"> <span class="songNum topRed">03.</span> <a target="_1" href="/play/65937.htm" class="songName">再回首</a></li><li><input type="checkbox" value="59930@" name="Url" class="check"> <span class="songNum">04.</span> <a target="_1" href="/play/59930.htm" class="songName cBlue">突然的自我</a></li><li><input type="checkbox" value="1462@" name="Url" class="check"> <span class="songNum">05.</span> <a target="_1" href="/play/1462.htm" class="songName">甘心情愿</a></li></ol></div>'
result = re.findall('songName.*?>(.*?)</a>.*?',html)
print(result)
- 返回值:['大海', '天路', '再回首', '突然的自我', '甘心情愿'] *
-
re.sub---替換字符串中每一個匹配的子串后返回替換后的字符串继准。
import re
content = 'Hello 3232 4324 World_This is a Regex Demo'
content = re.sub('\d+','',content)#把數(shù)字替換為空
print(content)
import re
content = 'Hello 3232 4324 World_This is a Regex Demo'
content = re.sub('\d+','Replacement',content)#數(shù)字部分都替換成‘replacement’
print(content)
如果替換的結(jié)果包含想替換的內(nèi)容怎么辦,比如像把這2段數(shù)字前面加上No.矮男,但數(shù)字要保留移必,怎么辦?
import re
content = 'Hello 3232 4324 World_This is a Regex Demo'
content = re.sub('(\d+)',r'No.\1',content)#用r''中間的是原生字符串不用轉(zhuǎn)義了毡鉴。先把patten小括號括起來崔泵,替換內(nèi)容加\n.這個n表示第幾個小括號的內(nèi)容替換成這樣。
print(content)
- 結(jié)果:Hello No.3232 No.4324 World_This is a Regex Demo
-
re.compile---將正則字符串編譯成正則表達式對象
將正則字符串編譯成正則表達式對象猪瞬,便于復(fù)用該匹配模式
import re
content = 'Hello 3232 4324 World_This is a Regex Demo'
result = re.match('^He.*?(\d+).*mo$',content,re.S)#用正則字符串匹配
myPatten = re.compile('^He.*?(\d+).*mo$',re.S)#編譯正則表達式對象憎瘸。
result = re.match(mypatten,content)#2種方法一樣
print(result)
-
令人期待的實戰(zhàn)例子
爬取豆瓣讀書
讀取https://book.douban.com 新書速遞中的書名、作者陈瘦、出版社
import requests
import re
content = requests.get('https://book.douban.com/').text
#print(content)
pattern = re.compile('<li.*?cover.*?href="(.*?)".*?title="(.*?)".*?more-meta.*?author">(.*?)</span>.*?year">(.*?)</span>.*?</li>',re.S)
#print(pattern)
results = re.findall(pattern,content)
print(results)
這個例子我跑失敗了幌甘,卡死...