怎么理解并掌握python正則表達式和re模塊

這篇文章主要介紹“怎么理解并掌握python正則表達式和re模塊”,在日常操作中,相信很多人在怎么理解并掌握python正則表達式和re模塊問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么理解并掌握python正則表達式和re模塊”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

創(chuàng)新互聯(lián)2013年至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務公司,擁有項目網(wǎng)站制作、成都做網(wǎng)站網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元遷西做網(wǎng)站,已為上家服務,為遷西各地企業(yè)和個人服務,聯(lián)系電話:18982081108

1.正則表達式

正則表達式,又稱規(guī)則表達式。(英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE),計算機科學的一個概念。正則表達式通常被用來檢索、替換那些符合某個模式(規(guī)則)的文本。

下面是正則表達式常見的使用場景:

檢查字符串的合法性

驗證用戶名 (a-z,0-9,不能全是數(shù)字,不能全是字母)

驗證郵箱格式 (xxx@qq.com)

驗證電話號碼 (11位數(shù)字)

驗證身份證 (18位 )

驗證號碼格式(5-12純數(shù)字,第一位不能為0);

提取字符串中信息

提取一條短信中數(shù)字;

提取文件名的后綴;

采集器(網(wǎng)絡爬蟲)

替換字符串

替換字符串中的非法字符;

對電話號碼進行屏蔽;(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ù)默認遇到換行符 '\n’會終止當前的匹配,即不匹配換行符,每一行單獨匹配,因此會出現(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ù)量詞默認是貪婪的(在少數(shù)語言里也可能是默認非貪婪),總是嘗試匹配盡可能多的字符;

非貪婪則相反,總是嘗試匹配盡可能少的字符。

在"*","?","+","{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ù),其實在正則表達式模塊中還有一些函數(shù)可以很方便的對字符串進行操作。re模塊的使用可以分為兩種:第一種是對象式的方式,第二種是函數(shù)式的方式。

2.1 re.match

match() 用于查找字符串的頭部(也可以指定起始位置),它是一次匹配,只要找到了一個匹配的結(jié)果就返回,而不是查找所有匹配的結(jié)果。它的一般使用形式如下:

match(pattern, string[, flag])

其中,pattern是正則表達式規(guī)則字符串,string 是待匹配的字符串,flag 是可選參數(shù)。

當匹配成功時,返回一個 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])

當匹配成功時,返回一個 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: 默認是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ù)為對應的正則表達式,第二個參數(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格式的子串,然后把子串當做參數(shù)輸入repl中,默認的repl功能可以看成是函數(shù),即不論我輸入的子串是什么樣的,輸出都用repl參數(shù)代替,此處repl無法跟子串產(chǎn)生關(guān)系

def replace(string,repl):

return repl

如果我們要讓輸出的repl和子串產(chǎn)生關(guān)系,如將字符串中的電話號碼15654862043輸出成1565****043,僅僅通過設定一個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ù)將正則表達式的字符串形式編譯為一個 Pattern 對象。通過該對象提供的一系列方法對文本進行匹配查找,獲得匹配結(jié)果(Match對象)。編譯可以實現(xiàn)更高效的匹配查找等。

compile()函數(shù)

compile() 函數(shù)用于編譯正則表達式,生成一個 Pattern 對象,它的一般使用形式如下:

import re

# 將正則表達式編譯成 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ù)復用

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ù)編程語言相同,正則表達式里使用"\"作為轉(zhuǎn)義字符,這就可能造成反斜杠困擾。假如你需要匹配文本中的字符"\\",那么使用編程語言表示的正則表達式里將需要4個反斜杠"\":前兩個和后兩個分別用于在編程語言里轉(zhuǎn)義成反斜杠,轉(zhuǎn)換成兩個反斜杠后再在正則表達式里轉(zhuǎn)義成一個反斜杠。

Python里的原生字符串很好地解決了這個問題,有了原生字符串,你再也不用擔心是不是漏寫了反斜杠,寫出來的表達式也更直觀。

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

以上就是郵箱

'''

萬能正則

(.*?) 匹配除了換行以外的任意字符串。無論長短,最多匹配一次,非貪婪匹配。

這個正則表達式可以解決你想要提取的大部分數(shù)據(jù),在寫正則表達式的時候可以首先嘗試這個組合,也許能達到事半功倍的效果。并且常常結(jié)合re.findall()函數(shù)。

2.9 案例:抓取電影天堂數(shù)據(jù)

'''

電影天堂思路:

1. 進入最新的電影更多 --> 更多的第一頁

2. 翻頁 https://www.dytt8.net/html/gndy/dyzz/list_23_{}.html

1. > 提取每一頁的數(shù)據(jù)電影的詳情頁網(wǎng)址

2. > 發(fā)送請求 得到響應

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'https://www.dytt8.net/html/gndy/dyzz/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ā)請求 得到詳情頁的響應

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ā)送請求得到響應 提取響應中的歌曲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)址 然后得到響應

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正則表達式和re模塊”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

網(wǎng)站題目:怎么理解并掌握python正則表達式和re模塊
網(wǎng)頁路徑:http://muchs.cn/article18/ihscdp.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化網(wǎng)站策劃、微信小程序、企業(yè)網(wǎng)站制作、響應式網(wǎng)站、定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化