python--re模組, 正則表示式
正則表示式是對字串操作的一種邏輯公式.我們一般使用正則表示式對字串進行匹配和過濾.使用這則的優缺點:
有點:靈活,功能性強,邏輯性強
缺點: 上手男.一旦上手,會愛上這個東西
工具: 各大文字編輯器一般都由正則匹配功能. 我們可以去http://tool.chinaz.com/regex/ 線上使用工具進行測試
1. 正則表示式,匹配字串
元字元
字元組很簡單用[]括起來,在[]中出現的內容會被匹配,例如:[abc] 匹配a或b或c
如果字元組中的內容過多還可以使用-,
[a-zA-Z0-9] 匹配的是字母a-z或A-z或0-9中的任意一個
. 匹配除換行符以外的任意字元 \w 匹配字母或數字或下劃線 \s 匹配任意的空白符 \d 匹配數字 \n 匹配一個換行符 \t 匹配一個製表符 \b 匹配一個單詞的邊界 ^ 匹配字串的開始 & 匹配字串的結尾 \W 匹配非字母或數字或下劃線 \D 匹配非數字 \S 匹配非空白符 a|b 匹配字元a或字元b () 匹配括號內的表示式,也表示一個組 [...] 匹配字元組中的字元 [^...] 匹配除了字元組中字元的所有字元
量詞
一次性匹配多個字元就要用到量詞
* 重複0次或更多次
+ 重複1次或更多次
? 重複0次或1次
{n} 重複n次
{n,} 重複n次或更多次
{n,m} 重複n到m次
惰性匹配和貪婪匹配
在量詞中的 * , +, {} 都屬於貪婪匹配,就是儘可能多的匹配到結果
.*? 儘可能少的匹配,表示惰性匹配 str: <div>胡辣湯</div> reg: <.*> 結果: <div>胡辣湯</div> str: <div>胡辣湯</div> reg: <.*?> 結果: <div> </div> str: <div>胡辣湯</div> reg: <(div|/div*)?> 結果: <div> </div>
惰性匹配和貪婪匹配
貪婪
.* 儘可能多的匹配
.+
惰性:
.*?哈哈 儘可能少的匹配
分組:
使用括號()進行分組
轉義:
在正則表示式中,有很多特殊意義的元字元,如果要在正則中匹配正常的\n而不是"換行符"就需要對"\"進行轉義,太麻煩了,
所以我們就用到了r'\n'這個概念,為了打出 str ->' \n' ,此時的正則是r'\\n'就可以了
2. re 模組
在python中使用正則. re
(?P<name>正則) 用的時候直接 group("name")就可以了
1. search() 搜尋. 搜尋到第一個結果返回
search和match的區別: search查詢. 找到了結果就返回. match. 從頭開始匹配.
r = re.search("\d+","電話號碼123456789")
print(r) # <_sre.SRE_Match object; span=(4, 13), match='123456789'>
print(r.group()) # 123456789
2. match() 匹配. 收到一個結果返回. 從頭開始匹配
r = re.match("\d+","電話號碼123456789")
print(r)
print(r.group())
結果
<_sre.SRE_Match object; span=(0, 3), match='123'>
123
所以顯示出match是從字串開始進行匹配
r = re.match("\d+","12312電話號碼123456789")
print(r)
print(r.group())
結果
<_sre.SRE_Match object; span=(0, 5), match='12312'>
12312
3. findall() 查詢所有匹配結果
r = re.findall("\d+","電話號碼123456789")
print(r) # ['123456789']
4. finditer() 返回迭代器.
result = re.finditer(r"姓名:(?P<name>.*?), 愛好:(?P<hobby>.*?),", "姓名:小名, 愛好:女,")
for el in result:
print(el.group("name"), el.group("hobby"))
結果
<callable_iterator object at 0x000002044EBDF2E8>
<callable_iterator object at 0x000002044EBDF2E8>
小名 女
5. compile() 編譯
reg = re.compile(r'\d+') # 載入了一段正則
lst = reg.findall("呵呵, 笨蛋才不去134呢.他要去1123了")
print(lst)
結果
['134', '1123']
6. group("name") 獲取資料
result = re.finditer(r"姓名:(?P<name>.*?), 愛好:(?P<hobby>.*?),", "姓名:小名, 愛好:女,")
for el in result:
print(el.group("name"), el.group("hobby"))
結果
<callable_iterator object at 0x000002044EBDF2E8>
<callable_iterator object at 0x000002044EBDF2E8>
小名 女
7. re.S 幹掉 . 的換行
在網頁原始碼中有許多空白, re.S就是為了去掉這些空白
# 爬取電影天堂
from urllib.request import urlopen
content = urlopen("https://www.dytt8.net/html/gndy/dyzz/20181219/57954.html").read().decode("gbk")
# print(content)
reg = r'<div id="Zoom">.*?片 名(?P<name>.*?)<br />◎年 代(?P<years>.*?)<br />.*?◎上映日期(?P<date>.*?)<br />'+ \
'.*?◎主 演(?P<main>.*?)◎簡 介.*?<td style="WORD-WRAP: break-word" bgcolor="#fdfddf"><a href="(?P<download>.*?)">'
it = re.finditer(reg, content, re.S) # re.S 去掉.裡面的\n
for el in it:
print(el.group("name"))
print(el.group("years"))
print(el.group("date"))
print(el.group("main").replace("<br /> ", ", "))
print(el.group("download"))
8. (?:) 把表示式從python中的正則分組變為正則表示式中的分組
lst = re.findall(r"a(?:\d+)c", "a123456c") # 把括號python中的分組變成了原來正則表示式中的分組
print(lst)
lst = re.findall(r"a(\d+)c", "a123456c") # 把括號python中的分組變成了原來正則表示式中的分組
print(lst)
結果
['a123456c']
['123456']
3. 其他操作
1.sub,替換目標字串
ret = re.sub(r'\d+','__???__',"mike1446inn9988oeoeujt") # 把字串中的數字替換成__???__ print(ret)
結果
# mike__???__inn__???__oeoeujt
2.subn,替換目標字串並返回為元組,並對替換的次數計數
ret = re.subn(r'\d+','__???__',"mike1446inn9988oeoeujt")
print(ret)
結果
('mike__???__inn__???__oeoeujt', 2)
3.正則中的split()
ret = re.split('[ab]','qqqqeafiefubdkksd')
print(ret)
結果
['qqqqe', 'fiefu', 'dkksd']
注意事項:在匹配部分加上()之後所切出的結果是不同的
在匹配部分沒有加()的話,不保留匹配部分
ret = re.split("\d+","eklfj3fe4efji") print(ret) # ['eklfj', 'fe', 'efji']
在匹配部分加了()的話,保留匹配部分
ret1 = re.split("(\d+)","eklfj3fe4efji") print(ret1) # ['eklfj', '3', 'fe', '4', 'efji']