1. 程式人生 > >python--re模組, 正則表示式

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']