python re模块_python 正则表达式 (重点) re模块
京東的注冊(cè)頁(yè)面,打開(kāi)頁(yè)面我們就看到這些要求輸入個(gè)人信息的提示。
假如我們隨意的在手機(jī)號(hào)碼這一欄輸入一個(gè)11111111111,它會(huì)提示我們格式有誤。
這個(gè)功能是怎么實(shí)現(xiàn)的呢?
假如現(xiàn)在你用python寫(xiě)一段代碼,類似:
phone_number = input('please input your phone number :')
你怎么判斷這個(gè)phone_number是合法的呢?
根據(jù)手機(jī)號(hào)碼一共11位并且是只以13、14、15、18開(kāi)頭的數(shù)字這些特點(diǎn),我們用python寫(xiě)了如下代碼:
whileTrue:
phone_number= input('please input your phone number :')if len(phone_number) == 11\andphone_number.isdigit()\and (phone_number.startswith('13') \or phone_number.startswith('14') \or phone_number.startswith('15') \or phone_number.startswith('18')):print('是合法的手機(jī)號(hào)碼')else:print('不是合法的手機(jī)號(hào)碼')
low版
importre
phone_number= input('please input your phone number :')if re.match('^(13|14|15|18)[0-9]{9}$',phone_number):print('是合法的手機(jī)號(hào)碼')else:print('不是合法的手機(jī)號(hào)碼')
正則版
對(duì)比上面的兩種寫(xiě)法,此時(shí)此刻,我要問(wèn)你你喜歡哪種方法呀?你肯定還是會(huì)說(shuō)第一種,為什么呢?因?yàn)榈谝环N不用學(xué)呀!
但是如果現(xiàn)在有一個(gè)文件,我讓你從整個(gè)文件里匹配出所有的手機(jī)號(hào)碼。你用python給我寫(xiě)個(gè)試試?
但是學(xué)了今天的技能之后,分分鐘幫你搞定!
今天我們要學(xué)習(xí)python里的re模塊和正則表達(dá)式,學(xué)會(huì)了這個(gè)就可以幫我們解決剛剛的疑問(wèn)。正則表達(dá)式不僅在python領(lǐng)域,在整個(gè)編程屆都占有舉足輕重的地位。
不管以后你是不是去做python開(kāi)發(fā),只要你是一個(gè)程序員就應(yīng)該了解正則表達(dá)式的基本使用。如果未來(lái)你要在爬蟲(chóng)領(lǐng)域發(fā)展,你就更應(yīng)該好好學(xué)習(xí)這方面的知識(shí)。
但是你要知道,re模塊本質(zhì)上和正則表達(dá)式?jīng)]有一毛錢(qián)的關(guān)系。re模塊和正則表達(dá)式的關(guān)系 類似于 time模塊和時(shí)間的關(guān)系
你沒(méi)有學(xué)習(xí)python之前,也不知道有一個(gè)time模塊,但是你已經(jīng)認(rèn)識(shí)時(shí)間了12:30就表示中午十二點(diǎn)半(這個(gè)時(shí)間可好,一般這會(huì)兒就該下課了)。
時(shí)間有自己的格式,年月日時(shí)分秒,12個(gè)月,365天......已經(jīng)成為了一種規(guī)則。你也早就牢記于心了。time模塊只不過(guò)是python提供給我們的可以方便我們操作時(shí)間的一個(gè)工具而已
正則表達(dá)式本身也和python沒(méi)有什么關(guān)系,就是匹配字符串內(nèi)容的一種規(guī)則。
官方定義:正則表達(dá)式是對(duì)字符串操作的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個(gè)“規(guī)則字符串”,
這個(gè)“規(guī)則字符串”用來(lái)表達(dá)對(duì)字符串的一種過(guò)濾邏輯。
正則表達(dá)式
一說(shuō)規(guī)則我已經(jīng)知道你很暈了,現(xiàn)在就讓我們先來(lái)看一些實(shí)際的應(yīng)用。
首先你要知道的是,談到正則,就只和字符串相關(guān)了。在我給你提供的工具中,你輸入的每一個(gè)字都是一個(gè)字符串。
其次,如果在一個(gè)位置的一個(gè)值,不會(huì)出現(xiàn)什么變化,那么是不需要規(guī)則的。
比如你要用"1"去匹配"1",或者用"2"去匹配"2",直接就可以匹配上。這連python的字符串操作都可以輕松做到。
那么在之后我們更多要考慮的是在同一個(gè)位置上可以出現(xiàn)的字符的范圍。
字符組 : [字符組]
在同一個(gè)位置可能出現(xiàn)的各種字符組成了一個(gè)字符組,在正則表達(dá)式中用[]表示
字符分為很多類,比如數(shù)字、字母、標(biāo)點(diǎn)等等。
假如你現(xiàn)在要求一個(gè)位置"只能出現(xiàn)一個(gè)數(shù)字",那么這個(gè)位置上的字符只能是0、1、2...9這10個(gè)數(shù)之一。
字符組
正則
待匹配字符
匹配
結(jié)果
說(shuō)明
[0123456789]
8
True
在一個(gè)字符組里枚舉合法的所有字符,字符組里的任意一個(gè)字符
和"待匹配字符"相同都視為可以匹配
[0123456789]
a
False
由于字符組中沒(méi)有"a"字符,所以不能匹配
[0-9]
7
True
也可以用-表示范圍,[0-9]就和[0123456789]是一個(gè)意思
[a-z]
s
True
同樣的如果要匹配所有的小寫(xiě)字母,直接用[a-z]就可以表示
[A-Z]
B
True
[A-Z]就表示所有的大寫(xiě)字母
[0-9a-fA-F]
e
True
可以匹配數(shù)字,大小寫(xiě)形式的a~f,用來(lái)驗(yàn)證十六進(jìn)制字符
字符:
元字符
匹配內(nèi)容
.
匹配除換行符以外的任意字符
\w
匹配字母或數(shù)字或下劃線
\s
匹配任意的空白符
\d
匹配數(shù)字
\n
匹配一個(gè)換行符
\t
匹配一個(gè)制表符
\b
匹配一個(gè)單詞的結(jié)尾
^
匹配字符串的開(kāi)始
$
匹配字符串的結(jié)尾
\W
匹配非字母或數(shù)字或下劃線
\D
匹配非數(shù)字
\S
匹配非空白符
a|b
匹配字符a或字符b
()
匹配括號(hào)內(nèi)的表達(dá)式,也表示一個(gè)組
[...]
匹配字符組中的字符
[^...]
匹配除了字符組中字符的所有字符
re模塊下的常用方法
ret = re.findall('\d+','kjasdgk912798jkshf912847jzhsfk91278')print(ret)#一次性返回所有匹配到的項(xiàng),直接存在列表中
importre#ret = re.findall('\d+(?:\.\d+)?','1.2345+4.3')#?:寫(xiě)在一個(gè)分組的最開(kāi)始,表示在findall方法中取消這個(gè)分組的優(yōu)先級(jí)#1.2345 4.3#.2345 .3#print(ret)
例子2:#ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')#print(ret) 加上?:打印全部,不加打印oldboy
findall
注意:
1 findall的優(yōu)先級(jí)查詢:
import re
ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(ret) # ['oldboy'] 這是因?yàn)閒indall會(huì)優(yōu)先把匹配結(jié)果組里內(nèi)容返回,如果想要匹配結(jié)果,取消權(quán)限即可
ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')
print(ret) # ['www.oldboy.com']
ret = re.search('a', 'eva egon yuan').group()print(ret) #結(jié)果 : 'a'#函數(shù)會(huì)在字符串內(nèi)查找模式匹配,只到找到第一個(gè)匹配然后返回一個(gè)包含匹配信息的對(duì)象,該對(duì)象可以#通過(guò)調(diào)用group()方法得到匹配的字符串,如果字符串沒(méi)有匹配,則返回None。
search
注意:
s="2.22*33"
m=re.search("(\d+\.\d+)([*])(\d+)",s)
print(m.group(0)) 2.22*33
print(m.group(1)) 2.22
print(m.group(2)) *
print(m.group(3)) 33
ret = re.match('a', 'abc').group() #同search,不過(guò)只在字符串開(kāi)始處進(jìn)行匹配
print(ret)#結(jié)果 : 'a'
match
ret = re.split('[ab]', 'abcd') #先按'a'分割得到''和'bcd',在對(duì)''和'bcd'分別按'b'分割
print(ret) #['', '', 'cd']
#split中如果帶有分組,會(huì)在分割的同時(shí)保留被分割內(nèi)容中帶分組的部分#ret = re.split('(\d\d)','alex83wusir38egon20')#print(ret) ['alex', '83', 'wusir', '38', 'egon', '20', '']
split
ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1)#將數(shù)字替換成'H',參數(shù)1表示只替換1個(gè)
print(ret) #evaHegon4yuan4
sub
ret = re.subn('\d', 'H', 'eva3egon4yuan4')#將數(shù)字替換成'H',返回元組(替換的結(jié)果,替換了多少次)
print(ret) ('evaHegonHyuanH', 3)
subn
obj = re.compile('\d{3}') #將正則表達(dá)式編譯成為一個(gè) 正則表達(dá)式對(duì)象,規(guī)則要匹配的是3個(gè)數(shù)字
ret = obj.search('abc123eeee') #正則表達(dá)式對(duì)象調(diào)用search,參數(shù)為待匹配的字符串
print(ret.group()) #結(jié)果 : 123
compile
ret = re.finditer('\d', 'ds3sy4784a') #finditer返回一個(gè)存放匹配結(jié)果的迭代器
print(ret) #
print(next(ret).group()) #查看第一個(gè)結(jié)果
print(next(ret).group()) #查看第二個(gè)結(jié)果
print([i.group() for i in ret]) #查看剩余的左右結(jié)果
finditer
綜合練習(xí)與擴(kuò)展
importre
ret= re.search("<(?P\w+)>\w+(?P=tag_name)>","
hello
")#還可以在分組中利用?的形式給分組起名字#獲取的匹配結(jié)果可以直接用group('名字')拿到對(duì)應(yīng)的值print(ret.group('tag_name')) #結(jié)果 :h1
print(ret.group()) #結(jié)果 :
hello
ret= re.search(r"<(\w+)>\w+\1>","
hello
")#如果不給組起名字,也可以用\序號(hào)來(lái)找到對(duì)應(yīng)的組,表示要找的內(nèi)容和前面的組內(nèi)容一致#獲取的匹配結(jié)果可以直接用group(序號(hào))拿到對(duì)應(yīng)的值print(ret.group(1))print(ret.group()) #結(jié)果 :
hello
匹配標(biāo)簽
importre
ret=re.findall(r"\d+","1-2*(60+(-40.35/5)-(-4*3))")print(ret) #['1', '2', '60', '40', '35', '5', '4', '3']
ret=re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")print(ret) #['1', '-2', '60', '', '5', '-4', '3']
ret.remove("")print(ret) #['1', '-2', '60', '5', '-4', '3']
匹配整數(shù)
1、 匹配一段文本中的每行的郵箱
http://blog.csdn.net/make164492212/article/details/51656638
2、 匹配一段文本中的每行的時(shí)間字符串,比如:‘1990-07-12’;
分別取出1年的12個(gè)月(^(0?[1-9]|1[0-2])$)、
一個(gè)月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$3、 匹配qq號(hào)。(騰訊QQ號(hào)從10000開(kāi)始) [1,9][0,9]{4,}4、 匹配一個(gè)浮點(diǎn)數(shù)。 ^(-?\d+)(\.\d+)?$ 或者 -?\d+\.?\d*
5、 匹配漢字。 ^[\u4e00-\u9fa5]{0,}$6、 匹配出所有整數(shù)
數(shù)字匹配
importrequestsimportreimportjsondefgetPage(url):
response=requests.get(url)returnresponse.textdefparsePage(s):
com=re.compile('
.*? .*? (?P\d+).*?(?P.*?)''.*?.*?(?P.*?)評(píng)價(jià)',re.S)
ret=com.finditer(s)for i inret:yield{"id":i.group("id"),"title":i.group("title"),"rating_num":i.group("rating_num"),"comment_num":i.group("comment_num"),
}defmain(num):
url='https://movie.douban.com/top250?start=%s&filter='%num
response_html=getPage(url)
ret=parsePage(response_html)print(ret)
f=open("move_info7","a",encoding="utf8")for obj inret:print(obj)
data=json.dumps(obj,ensure_ascii=False)
f.write(data+"\n")if __name__ == '__main__':
count=0for i in range(10):
main(count)
count+=25
爬蟲(chóng)練習(xí)簡(jiǎn)單版
importreimportjsonfrom urllib.request importurlopendefgetPage(url):
response=urlopen(url)return response.read().decode('utf-8')defparsePage(s):
com=re.compile('
.*? .*?(?P\d+).*?(?P.*?)''.*?.*?(?P.*?)評(píng)價(jià)', re.S)
ret=com.finditer(s)for i inret:yield{"id": i.group("id"),"title": i.group("title"),"rating_num": i.group("rating_num"),"comment_num": i.group("comment_num"),
}defmain(num):
url= 'https://movie.douban.com/top250?start=%s&filter=' %num
response_html=getPage(url)
ret=parsePage(response_html)print(ret)
f= open("move_info7", "a", encoding="utf8")for obj inret:print(obj)
data=str(obj)
f.write(data+ "\n")
count=0for i in range(10):
main(count)
count+= 25
爬蟲(chóng)練習(xí)高級(jí)版
flags有很多可選值:
re.I(IGNORECASE)忽略大小寫(xiě),括號(hào)內(nèi)是完整的寫(xiě)法
re.M(MULTILINE)多行模式,改變^和$的行為
re.S(DOTALL)點(diǎn)可以匹配任意字符,包括換行符
re.L(LOCALE)做本地化識(shí)別的匹配,表示特殊字符集 \w, \W, \b, \B, \s, \S 依賴于當(dāng)前環(huán)境,不推薦使用
re.U(UNICODE) 使用\w \W \s \S \d \D使用取決于unicode定義的字符屬性。在python3中默認(rèn)使用該flag
re.X(VERBOSE)冗長(zhǎng)模式,該模式下pattern字符串可以是多行的,忽略空白字符,并可以添加注釋
flags
總結(jié)
以上是生活随笔為你收集整理的python re模块_python 正则表达式 (重点) re模块的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2019.11.4 英语学习
- 下一篇: 《Python程序设计(第3版)》[美]