python 正則表達式 (重點) re模塊
阿新 • • 發佈:2018-07-17
db2 idt 好的 騰訊qq regex clas def 12個 函數
京東的註冊頁面,打開頁面我們就看到這些要求輸入個人信息的提示。
假如我們隨意的在手機號碼這一欄輸入一個11111111111,它會提示我們格式有誤。
這個功能是怎麽實現的呢?
假如現在你用python寫一段代碼,類似:
phone_number = input(‘please input your phone number : ‘)
你怎麽判斷這個phone_number是合法的呢?
根據手機號碼一共11位並且是只以13、14、15、18開頭的數字這些特點,我們用python寫了如下代碼:
while True: phone_number = input(‘please input your phone number :low版‘) if len(phone_number) == 11 and phone_number.isdigit() and (phone_number.startswith(‘13‘) or phone_number.startswith(‘14‘) or phone_number.startswith(‘15‘) or phone_number.startswith(‘18‘)): print(‘是合法的手機號碼‘) else:print(‘不是合法的手機號碼‘)
import re phone_number = input(‘please input your phone number : ‘) if re.match(‘^(13|14|15|18)[0-9]{9}$‘,phone_number): print(‘是合法的手機號碼‘) else: print(‘不是合法的手機號碼‘)正則版
對比上面的兩種寫法,此時此刻,我要問你你喜歡哪種方法呀?你肯定還是會說第一種,為什麽呢?因為第一種不用學呀!
但是如果現在有一個文件,我讓你從整個文件裏匹配出所有的手機號碼。你用python給我寫個試試?
但是學了今天的技能之後,分分鐘幫你搞定!
今天我們要學習python裏的re模塊和正則表達式,學會了這個就可以幫我們解決剛剛的疑問。正則表達式不僅在python領域,在整個編程屆都占有舉足輕重的地位。
不管以後你是不是去做python開發,只要你是一個程序員就應該了解正則表達式的基本使用。如果未來你要在爬蟲領域發展,你就更應該好好學習這方面的知識。 但是你要知道,re模塊本質上和正則表達式沒有一毛錢的關系。re模塊和正則表達式的關系 類似於 time模塊和時間的關系 你沒有學習python之前,也不知道有一個time模塊,但是你已經認識時間了 12:30就表示中午十二點半(這個時間可好,一般這會兒就該下課了)。 時間有自己的格式,年月日時分秒,12個月,365天......已經成為了一種規則。你也早就牢記於心了。time模塊只不過是python提供給我們的可以方便我們操作時間的一個工具而已
正則表達式本身也和python沒有什麽關系,就是匹配字符串內容的一種規則。
官方定義:正則表達式是對字符串操作的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個“規則字符串”,
這個“規則字符串”用來表達對字符串的一種過濾邏輯。
正則表達式
一說規則我已經知道你很暈了,現在就讓我們先來看一些實際的應用。在線測試工具 http://tool.chinaz.com/regex/
首先你要知道的是,談到正則,就只和字符串相關了。在我給你提供的工具中,你輸入的每一個字都是一個字符串。
其次,如果在一個位置的一個值,不會出現什麽變化,那麽是不需要規則的。
比如你要用"1"去匹配"1",或者用"2"去匹配"2",直接就可以匹配上。這連python的字符串操作都可以輕松做到。
那麽在之後我們更多要考慮的是在同一個位置上可以出現的字符的範圍。
字符組 : [字符組] 在同一個位置可能出現的各種字符組成了一個字符組,在正則表達式中用[]表示 字符分為很多類,比如數字、字母、標點等等。 假如你現在要求一個位置"只能出現一個數字",那麽這個位置上的字符只能是0、1、2...9這10個數之一。字符組
正則 |
待匹配字符 |
匹配 |
說明 |
[0123456789] |
8 |
True |
在一個字符組裏枚舉合法的所有字符,字符組裏的任意一個字符 |
[0123456789] |
a |
False |
由於字符組中沒有"a"字符,所以不能匹配 |
[0-9] |
7 |
True |
也可以用-表示範圍,[0-9]就和[0123456789]是一個意思 |
[a-z] |
s |
True |
同樣的如果要匹配所有的小寫字母,直接用[a-z]就可以表示 |
[A-Z] |
B |
True |
[A-Z]就表示所有的大寫字母 |
[0-9a-fA-F] |
e |
True |
可以匹配數字,大小寫形式的a~f,用來驗證十六進制字符 |
字符:
元字符 |
匹配內容 |
. | 匹配除換行符以外的任意字符 |
\w | 匹配字母或數字或下劃線 |
\s | 匹配任意的空白符 |
\d | 匹配數字 |
\n | 匹配一個換行符 |
\t | 匹配一個制表符 |
\b | 匹配一個單詞的結尾 |
^ | 匹配字符串的開始 |
$ | 匹配字符串的結尾 |
\W |
匹配非字母或數字或下劃線 |
\D |
匹配非數字 |
\S |
匹配非空白符 |
a|b |
匹配字符a或字符b |
() |
匹配括號內的表達式,也表示一個組 |
[...] |
匹配字符組中的字符 |
[^...] |
匹配除了字符組中字符的所有字符 |
re模塊下的常用方法
ret = re.findall(‘\d+‘,‘kjasdgk912798jkshf912847jzhsfk91278‘) print(ret) # 一次性返回所有匹配到的項,直接存在列表中 import re # ret = re.findall(‘\d+(?:\.\d+)?‘,‘1.2345+4.3‘) # ?:寫在一個分組的最開始,表示在findall方法中取消這個分組的優先級 # 1.2345 4.3 # .2345 .3 # print(ret) 例子2: # ret = re.findall(‘www.(?:baidu|oldboy).com‘, ‘www.oldboy.com‘) # print(ret) 加上?:打印全部,不加打印oldboyfindall
註意:
1 findall的優先級查詢:
import re ret = re.findall(‘www.(baidu|oldboy).com‘, ‘www.oldboy.com‘) print(ret) # [‘oldboy‘] 這是因為findall會優先把匹配結果組裏內容返回,如果想要匹配結果,取消權限即可 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) #結果 : ‘a‘ # 函數會在字符串內查找模式匹配,只到找到第一個匹配然後返回一個包含匹配信息的對象,該對象可以 # 通過調用group()方法得到匹配的字符串,如果字符串沒有匹配,則返回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,不過只在字符串開始處進行匹配 print(ret) #結果 : ‘a‘match
ret = re.split(‘[ab]‘, ‘abcd‘) # 先按‘a‘分割得到‘‘和‘bcd‘,在對‘‘和‘bcd‘分別按‘b‘分割 print(ret) # [‘‘, ‘‘, ‘cd‘] # split中如果帶有分組,會在分割的同時保留被分割內容中帶分組的部分 # ret = re.split(‘(\d\d)‘,‘alex83wusir38egon20‘) # print(ret) [‘alex‘, ‘83‘, ‘wusir‘, ‘38‘, ‘egon‘, ‘20‘, ‘‘]split
ret = re.sub(‘\d‘, ‘H‘, ‘eva3egon4yuan4‘, 1)#將數字替換成‘H‘,參數1表示只替換1個 print(ret) #evaHegon4yuan4sub
ret = re.subn(‘\d‘, ‘H‘, ‘eva3egon4yuan4‘)#將數字替換成‘H‘,返回元組(替換的結果,替換了多少次) print(ret) (‘evaHegonHyuanH‘, 3)subn
obj = re.compile(‘\d{3}‘) #將正則表達式編譯成為一個 正則表達式對象,規則要匹配的是3個數字 ret = obj.search(‘abc123eeee‘) #正則表達式對象調用search,參數為待匹配的字符串 print(ret.group()) #結果 : 123compile
ret = re.finditer(‘\d‘, ‘ds3sy4784a‘) #finditer返回一個存放匹配結果的叠代器 print(ret) # <callable_iterator object at 0x10195f940> print(next(ret).group()) #查看第一個結果 print(next(ret).group()) #查看第二個結果 print([i.group() for i in ret]) #查看剩余的左右結果finditer
綜合練習與擴展
import re ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>") #還可以在分組中利用?<name>的形式給分組起名字 #獲取的匹配結果可以直接用group(‘名字‘)拿到對應的值 print(ret.group(‘tag_name‘)) #結果 :h1 print(ret.group()) #結果 :<h1>hello</h1> ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>") #如果不給組起名字,也可以用\序號來找到對應的組,表示要找的內容和前面的組內容一致 #獲取的匹配結果可以直接用group(序號)拿到對應的值 print(ret.group(1)) print(ret.group()) #結果 :<h1>hello</h1>匹配標簽
import re 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‘]匹配整數
1、 匹配一段文本中的每行的郵箱 http://blog.csdn.net/make164492212/article/details/51656638 2、 匹配一段文本中的每行的時間字符串,比如:‘1990-07-12’; 分別取出1年的12個月(^(0?[1-9]|1[0-2])$)、 一個月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$ 3、 匹配qq號。(騰訊QQ號從10000開始) [1,9][0,9]{4,} 4、 匹配一個浮點數。 ^(-?\d+)(\.\d+)?$ 或者 -?\d+\.?\d* 5、 匹配漢字。 ^[\u4e00-\u9fa5]{0,}$ 6、 匹配出所有整數數字匹配
import requests import re import json def getPage(url): response=requests.get(url) return response.text def parsePage(s): com=re.compile(‘<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>‘ ‘.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)評價</span>‘,re.S) ret=com.finditer(s) for i in ret: yield { "id":i.group("id"), "title":i.group("title"), "rating_num":i.group("rating_num"), "comment_num":i.group("comment_num"), } def main(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 in ret: print(obj) data=json.dumps(obj,ensure_ascii=False) f.write(data+"\n") if __name__ == ‘__main__‘: count=0 for i in range(10): main(count) count+=25爬蟲練習簡單版
import re import json from urllib.request import urlopen def getPage(url): response = urlopen(url) return response.read().decode(‘utf-8‘) def parsePage(s): com = re.compile( ‘<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>‘ ‘.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)評價</span>‘, re.S) ret = com.finditer(s) for i in ret: yield { "id": i.group("id"), "title": i.group("title"), "rating_num": i.group("rating_num"), "comment_num": i.group("comment_num"), } def main(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 in ret: print(obj) data = str(obj) f.write(data + "\n") count = 0 for i in range(10): main(count) count += 25爬蟲練習高級版
flags有很多可選值: re.I(IGNORECASE)忽略大小寫,括號內是完整的寫法 re.M(MULTILINE)多行模式,改變^和$的行為 re.S(DOTALL)點可以匹配任意字符,包括換行符 re.L(LOCALE)做本地化識別的匹配,表示特殊字符集 \w, \W, \b, \B, \s, \S 依賴於當前環境,不推薦使用 re.U(UNICODE) 使用\w \W \s \S \d \D使用取決於unicode定義的字符屬性。在python3中默認使用該flag re.X(VERBOSE)冗長模式,該模式下pattern字符串可以是多行的,忽略空白字符,並可以添加註釋flags
在線測試工具 http://tool.chinaz.com/regex/
python 正則表達式 (重點) re模塊