這篇文章主要介紹“怎么理解并掌握python正則表達(dá)式和re模塊”,在日常操作中,相信很多人在怎么理解并掌握python正則表達(dá)式和re模塊問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么理解并掌握python正則表達(dá)式和re模塊”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
創(chuàng)新互聯(lián)建站專注于企業(yè)營銷型網(wǎng)站建設(shè)、網(wǎng)站重做改版、招遠(yuǎn)網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、H5場景定制、成都商城網(wǎng)站開發(fā)、集團公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)公司、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為招遠(yuǎn)等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。1.正則表達(dá)式
正則表達(dá)式,又稱規(guī)則表達(dá)式。(英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE),計算機科學(xué)的一個概念。正則表達(dá)式通常被用來檢索、替換那些符合某個模式(規(guī)則)的文本。
下面是正則表達(dá)式常見的使用場景:
檢查字符串的合法性
驗證用戶名 (a-z,0-9,不能全是數(shù)字,不能全是字母)
驗證郵箱格式 (xxx@qq.com)
驗證電話號碼 (11位數(shù)字)
驗證身份證 (18位 )
驗證號碼格式(5-12純數(shù)字,第一位不能為0);
提取字符串中信息
提取一條短信中數(shù)字;
提取文件名的后綴;
采集器(網(wǎng)絡(luò)爬蟲)
替換字符串
替換字符串中的非法字符;
對電話號碼進行屏蔽;(1852****0102)
替換占位符 “hello {{name}} ” hello 王老二 (模板框架)
分割字符串
將一個字符串按照指定的規(guī)則進行分割;
通俗地說,正則的功能是檢索特定形式的字符串,對象是字符串。
1.1 元字符
使用元字符匹配單個字符
字符 功能
. 匹配任意1個字符(除了\n)
[ ] 匹配[ ]中列舉的字符
\d 匹配數(shù)字,即0-9
\D 匹配非數(shù)字,即不是數(shù)字
\s 匹配空白,即 空格,tab鍵
\S 匹配非空白
\w 匹配單詞字符,即a-z、A-Z、0-9、_
\W 匹配非單詞字符
* 匹配前一個字符出現(xiàn)0次或者無限次,即可有可無
+ 匹配前一個字符出現(xiàn)1次或者無限次,即至少有1次
import re
text = '''
這是用來匹配的字符串
from:1427319758@qq.com
tel:88888888
'''
針對上述字符串進行元字符的正則匹配演示
使用點.匹配任意字符
res = re.findall('.',text)
print(res)
運行結(jié)果(注意返回的是列表):
['這', '是', '用', '來', '匹', '配', '的', '字', '符', '串', 'f', 'r', 'o', 'm', ':', '1', '4', '2', '7', '3', '1', '9', '7', '5', '8', '@', 'q', 'q', '.', 'c', 'o', 'm', 't', 'e', 'l', ':', '8', '8', '8', '8', '8', '8', '8', '8']
\d匹配數(shù)字
res = re.findall('\d',text)
print(res)
運行結(jié)果:
['1', '4', '2', '7', '3', '1', '9', '7', '5', '8', '8', '8', '8', '8', '8', '8', '8', '8']
+ * 匹配多個字符
res = re.findall('\d+',text)
res_1 = re.findall('\d*',text)
print(res,res_1)
運行結(jié)果:
['1427319758', '88888888']
['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '1427319758', '', '', '', '', '', '', '', '', '', '', '', '', '88888888', '', '']
*匹配前一字符可以是0次,因此\d*會匹配每個不是數(shù)字的字符,即為空。\d+等同\d\d*
[](字符集)
人為規(guī)定只能匹配出現(xiàn)在字符集中的字符,如要找尋字符串中的qq號,qq號不能以0開頭,且位數(shù)是5~12
可用[1-9]\d{4,11}來限制
郵箱可能出現(xiàn)為字符串,可用[1-9a-zA-Z]\w+[@]\w+[.][a-zA-z]+可以匹配出任意常規(guī)格式的郵箱
res = re.findall('[1-9a-zA-Z]\w+[@]\w+[.][a-zA-z]+','''
1427319758@163.com開會就
1427319758@edu.cn是否
1427319758@xx.mail 阿薩德
asdfbglsafhlf上單發(fā)順豐打打分
''')
print(res)
運行結(jié)果:
['1427319758@163.com', '1427319758@edu.cn', '1427319758@xx.mail']
使用.*匹配任意多個字符
res = re.findall('.*',text)
print(res)
運行結(jié)果:
['', '這是用來匹配的字符串', '', 'from:1427319758@qq.com', '', 'tel:88888888', '', '']
由于re.findall()函數(shù)默認(rèn)遇到換行符 '\n’會終止當(dāng)前的匹配,即不匹配換行符,每一行單獨匹配,因此會出現(xiàn)空元素。
1.2 數(shù)量詞
使用數(shù)量詞匹配多個字符
字符 功能
{m} 匹配前一個字符出現(xiàn)m次
{m,n} 匹配前一個字符出現(xiàn)從m到n次
限制匹配字符出現(xiàn)的次數(shù)
res = re.findall('[1-9]\d{4,11}',text)
res_1 = re.findall('([1-9]\d{4,11})@',text)
print(res,res_1)
運行結(jié)果:
['1427319758', '88888888'] ['1427319758']
第一種方式匹配了同樣滿足規(guī)則的手機號,第二種方式是考慮到qq號隱藏在郵箱地址里,所以在后面加了@來限制匹配的區(qū)域,即只匹配@前的第1位非0的5-12位純數(shù)字。
1.3 精確匹配與泛匹配
泛匹配
泛匹配是匹配包括特征字符在內(nèi)的所有的東西
res = re.findall('Hello.*like','Hello world! I like python!')
print(res)
運行結(jié)果:
['Hello world! I like']
精確匹配
精確匹配是匹配括號里面的東西
res_1 = re.findall('Hello(.*)like','Hello world! I like python!')
print(res_1)
運行結(jié)果:
[' world! I ']
我想要Hello和like之間的字符,泛匹配的結(jié)果會包含首尾的特征字符Hello和like;而精確匹配只會得到特征字符之間的字符串。
1.4 貪婪匹配與非貪婪匹配
Python里數(shù)量詞默認(rèn)是貪婪的(在少數(shù)語言里也可能是默認(rèn)非貪婪),總是嘗試匹配盡可能多的字符;
非貪婪則相反,總是嘗試匹配盡可能少的字符。
在"*","?","+","{m,n}"后面加上?,使貪婪變成非貪婪。
res = re.findall('Hello(.*)like','Hello world! I like python! I like you!')
res_1 = re.findall('Hello(.*?)like','Hello world! I like python! I like you!')
print(res,res_1)
運行結(jié)果:
[' world! I like python! I ']
[' world! I ']
res返回的是貪婪匹配,它會在找到Hello后,匹配盡可能多的字符,然后在最后一個like停下;
res_1返回的是非貪婪匹配,它在找到Hello后,只匹配第一個like前的字符。
2. re模塊
一直以來我們都是使用 re.search() 函數(shù),其實在正則表達(dá)式模塊中還有一些函數(shù)可以很方便的對字符串進行操作。re模塊的使用可以分為兩種:第一種是對象式的方式,第二種是函數(shù)式的方式。
2.1 re.match
match() 用于查找字符串的頭部(也可以指定起始位置),它是一次匹配,只要找到了一個匹配的結(jié)果就返回,而不是查找所有匹配的結(jié)果。它的一般使用形式如下:
match(pattern, string[, flag])
其中,pattern是正則表達(dá)式規(guī)則字符串,string 是待匹配的字符串,flag 是可選參數(shù)。
當(dāng)匹配成功時,返回一個 Match 對象,如果沒有匹配上,則返回 None。
import re
pattern = 'Python'
string = 'dsgfaPythonahsdgjasghPythonasdjajsk'
result = re.match(pattern,string)
result_1 = re.match(pattern,string[5:])
print(result,result_1)
運行結(jié)果:
None
<_sre.SRE_Match object; span=(0, 6), match='Python'>
2.2 re.search
search() 用于查找字符串的任何位置,它也是一次匹配,只要找到了一個匹配的結(jié)果就返回,而不是查找所有匹配的結(jié)果,它的一般使用形式如下:
search(pattern, string[, flag])
當(dāng)匹配成功時,返回一個 Match 對象,如果沒有匹配上,則返回 None。
ret = re.search('\d+', "python = 9999, c = 7890, c++ = 12345")
print(ret.group())
運行結(jié)果:
9999
2.3 re.findall 劃重點!
上面的 match 和 search 方法都是一次匹配,只要找到了一個匹配的結(jié)果就返回。然而,在大多數(shù)時候,我們需要搜索整個字符串,獲得所有匹配的結(jié)果。findall() 的使用形式如下:
findall(pattern, string[, flag])
findall() 以列表形式返回全部能匹配的子串,如果沒有匹配,則返回一個空列表。
ret = re.findall(r"\d+", "python = 9999, c = 7890, c++ = 12345")
print(ret)
運行結(jié)果:
['9999', '7890', '12345']
2.4 re.split
split()按照能夠匹配的子串將字符串分割后返回列表,它的使用形式如下:
split(pattern, string[, maxsplit, flags])
其中,maxsplit 用于指定大分割次數(shù),不指定將全部分割。
'''
split():
分割字符串 去掉了匹配到的字符串
結(jié)果是列表形式
maxsplit: 默認(rèn)是0 表示全部切割
1 代表切割一次
2 代表切割兩次
'''
pattern = '\d+'
string = 'Pythonasdkjasd464654adhuiaghsdk564654akjsdhkashdkja'
result = re.split(pattern,string,2)
print(result)
運行結(jié)果:
['Pythonasdkjasd', 'adhuiaghsdk', 'akjsdhkashdkja']
實際上就是面向字符串操作的string.split的升級版
2.5 re.sub
sub()用于替換,使用形式如下:
sub(pattern, repl, string[, count, flags])
第一個參數(shù)為對應(yīng)的正則表達(dá)式,第二個參數(shù)為要替換成的字符串,第三個參數(shù)為源字符串,第四個參數(shù)為可選項,代表最多替換的次數(shù),如果忽略不寫,則會將符合模式的結(jié)果全部替換。
pattern = 'Java'
repl = '********'
string = 'kjasdJavaadhuiaghsdkJavaakjsd'
result = re.sub(pattern,repl,string,1)
print(result)
運行結(jié)果:
kjasd********adhuiaghsdkJavaakjsd
string.replace的升級版
參數(shù)flags
方法1:
ret = re.sub("\d+", '18', "age = 12")
print(ret)
運行結(jié)果:
age = 18
方法2 用函數(shù):
re.sub()的本質(zhì)是在字符串中檢索符合pattern格式的子串,然后把子串當(dāng)做參數(shù)輸入repl中,默認(rèn)的repl功能可以看成是函數(shù),即不論我輸入的子串是什么樣的,輸出都用repl參數(shù)代替,此處repl無法跟子串產(chǎn)生關(guān)系
def replace(string,repl):
return repl
如果我們要讓輸出的repl和子串產(chǎn)生關(guān)系,如將字符串中的電話號碼15654862043輸出成1565****043,僅僅通過設(shè)定一個repl字符串是不能實現(xiàn)的,就需要在repl處傳入一個函數(shù)。
import re
text = '''
15654561654
13905641750
15646575635
18976534547
'''
def replace(string):
string = string.group()
repl = string[0:4] + '****' + string[-4:-1]
return repl
ret = re.sub("\d+", repl = replace, string = text)
print(ret)
運行結(jié)果:
1565****165
1390****175
1564****563
1897****454
2.6 re.compile
使用 compile() 函數(shù)將正則表達(dá)式的字符串形式編譯為一個 Pattern 對象。通過該對象提供的一系列方法對文本進行匹配查找,獲得匹配結(jié)果(Match對象)。編譯可以實現(xiàn)更高效的匹配查找等。
compile()函數(shù)
compile() 函數(shù)用于編譯正則表達(dá)式,生成一個 Pattern 對象,它的一般使用形式如下:
import re
# 將正則表達(dá)式編譯成 Pattern 對象
pattern_1 = re.compile('\d+', re.S)
pattern_2 = re.compile('\D+', re.l)
pattern_3 = re.compile('\w+', re.S)
之前定義pattern都是不包括flags參數(shù)的,因此不用re.compile,僅用賦值語句讓pattern = ‘\d+’也能實現(xiàn),compile函數(shù)的優(yōu)點在于:1.可以包含flags參數(shù);2.形成模塊,便于后續(xù)復(fù)用
results1 = re.findall(pattern_1, '540775360@qq.com')
results2 = re.findall(pattern_2, "python = 9999, c = 7890, c++ = 12345")
results3 = re.findall(pattern_3, "python = 997")
print(results1, results2, results3)
2.7 原生字符串
>>> mm = "c:\\a\\b\\c"
>>> mm
'c:\\a\\b\\c'
>>> print(mm)
c:\a\b\c
>>> re.match("c:\\\\",mm).group()
'c:\\'
>>> ret = re.match("c:\\\\",mm).group()
>>> print(ret)
c:\
>>> ret = re.match("c:\\\\a",mm).group()
>>> print(ret)
c:\a
>>> ret = re.match(r"c:\\a",mm).group()
>>> print(ret)
c:\a
>>> ret = re.match(r"c:\a",mm).group()
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'NoneType' object has no attribute 'group'
>>>鄭州做流產(chǎn)多少錢 http://www.kdwtrl.com/
Python中字符串前面加上 r 表示原生字符串,
與大多數(shù)編程語言相同,正則表達(dá)式里使用"\"作為轉(zhuǎn)義字符,這就可能造成反斜杠困擾。假如你需要匹配文本中的字符"\\",那么使用編程語言表示的正則表達(dá)式里將需要4個反斜杠"\":前兩個和后兩個分別用于在編程語言里轉(zhuǎn)義成反斜杠,轉(zhuǎn)換成兩個反斜杠后再在正則表達(dá)式里轉(zhuǎn)義成一個反斜杠。
Python里的原生字符串很好地解決了這個問題,有了原生字符串,你再也不用擔(dān)心是不是漏寫了反斜杠,寫出來的表達(dá)式也更直觀。
>>> ret = re.match(r"c:\\a",mm).group()
>>> print(ret)
c:\a
2.8 匹配開頭結(jié)尾
字符 功能
^ 匹配字符串開頭
$ 匹配字符串結(jié)尾
末尾匹配
需求:匹配163.com的郵箱地址
#coding=utf-8
import re
email_list = ["xiaoWang@163.com", "xiaoWang@163.comheihei", ".com.xiaowang@qq.com"]
for email in email_list:
ret = re.match("[\w]{4,20}@163\.com", email)
if ret:
print("%s 是符合規(guī)定的郵件地址,匹配后的結(jié)果是:%s" % (email, ret.group()))
else:
print("%s 不符合要求" % email)
運行結(jié)果:
xiaoWang@163.com 是符合規(guī)定的郵件地址,匹配后的結(jié)果是:xiaoWang@163.com
xiaoWang@163.comheihei 是符合規(guī)定的郵件地址,匹配后的結(jié)果是:xiaoWang@163.com
.com.xiaowang@qq.com 不符合要求
完善后
email_list = ["xiaoWang@163.com", "xiaoWang@163.comheihei", ".com.xiaowang@qq.com"]
for email in email_list:
ret = re.match("[\w]{4,20}@163\.com$", email)
if ret:
print("%s 是符合規(guī)定的郵件地址,匹配后的結(jié)果是:%s" % (email, ret.group()))
else:
print("%s 不符合要求" % email)
運行結(jié)果:
xiaoWang@163.com 是符合規(guī)定的郵件地址,匹配后的結(jié)果是:xiaoWang@163.com
xiaoWang@163.comheihei 不符合要求
.com.xiaowang@qq.com 不符合要求
這個例子只用于展示,用來匹配郵箱是沒有意義的。因為它匹配不出末尾不是com但包含了郵箱信息的多行字符串,如
'''
xiaoWang@163.com
xiaoKang@163.com
以上就是郵箱
'''
萬能正則
(.*?) 匹配除了換行以外的任意字符串。無論長短,最多匹配一次,非貪婪匹配。
這個正則表達(dá)式可以解決你想要提取的大部分?jǐn)?shù)據(jù),在寫正則表達(dá)式的時候可以首先嘗試這個組合,也許能達(dá)到事半功倍的效果。并且常常結(jié)合re.findall()函數(shù)。
2.9 案例:抓取電影天堂數(shù)據(jù)
'''
電影天堂思路:
1. 進入最新的電影更多 --> 更多的第一頁
2. 翻頁 /tupian/20230522/pp 1. > 提取每一頁的數(shù)據(jù)電影的詳情頁網(wǎng)址
2. > 發(fā)送請求 得到響應(yīng)
3. > 正則提取鏈接
4. > 保存數(shù)據(jù)(文件)
抓取之前盡量熟悉網(wǎng)頁的布局和結(jié)構(gòu)!! 熟悉網(wǎng)址的關(guān)系, 經(jīng)常查找網(wǎng)頁源碼中的數(shù)據(jù)(Ctrl+F).
'''
import re
import requests
for page in range(1, 5):
url_list = f'/tupian/20230522/list_23_{page}.html& # 找到詳情頁的網(wǎng)址 先進入 列表頁
r_list = requests.get(url_list)
# 指定編碼
r_list.encoding = 'gb2312'
# 提取詳情頁的網(wǎng)址 返回列表
url_detail = re.findall('', r_list.text)
for u in url_detail:
url = 'https://www.dytt8.net' + u
# print(url)
# 再次發(fā)請求 得到詳情頁的響應(yīng)
response = requests.get(url)
# 也會亂碼
response.encoding = 'gb2312'
# 提取數(shù)據(jù)
result = re.findall('.*?', response.text)[0:]
print(result)
try:
with open('dytt.txt', 'a', encoding='utf-8') as fp:
# write 只能字符串 和 二進制的 不能寫字典 列表 等
fp.write(result[0]+'\n')
except:
print('沒有提取到數(shù)據(jù)!!')
'''
歌曲下載:
可見即可爬 電影(VIP) 歌曲
思路:
1. 抓包 找到翻頁 http://www.htqyy.com/genre/musicList/3?pageIndex=6&pageSize=20&order=hot
2. 進入上面的網(wǎng)址 提取歌曲id
3. 下載歌曲 http://f2.htqyy.com/play7/{id}/mp3/1
'''
import re
import requests
for page in range(1, 3): # 1, 2
# 翻頁的
url_song = f'http://www.htqyy.com/genre/musicList/3?pageIndex={page}&pageSize=20&order=hot'
# 發(fā)送請求得到響應(yīng) 提取響應(yīng)中的歌曲ID
response_song = requests.get(url_song)
# 提取ID 返回列表
id_songs = re.findall('value="(\d+)">
# 遍歷歌曲的id 然后下載
for ids in id_songs:
song_url = 'http://f2.htqyy.com/play7/{}/mp3/1'.format(ids)
try:
# 請求歌曲的網(wǎng)址 然后得到響應(yīng)
response = requests.get(song_url, timeout=5)
# 保存歌曲
with open(f'{ids}.mp3', 'wb') as fp:
fp.write(response.content)
except:
print(f'這個歌曲{ids}出錯')
到此,關(guān)于“怎么理解并掌握python正則表達(dá)式和re模塊”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
網(wǎng)頁標(biāo)題:怎么理解并掌握python正則表達(dá)式和re模塊-創(chuàng)新互聯(lián)
網(wǎng)頁網(wǎng)址:http://weahome.cn/article/dosoeh.html