通過前面章節的學習,我們可通過請求庫向服務器發出請求,然後服務器返回結果,其中包含網頁源碼,那麼怎麼將這些源碼解析爲我們需要的形式,一種方式就是通過正則表達式來匹配得到。
正則表達式是處理字符串的強大工具,有了它,實現字符串的檢索、替換、匹配驗證都不在話下。
常用匹配規則
模式 |
描述 |
\w |
匹配字母、數字和下劃線 |
\W |
匹配不是字母、數字及下劃線的字符 |
\s |
匹配任意空白字符,等價於[\t\n\t\f] |
\S |
匹配任意非空字符 |
\d |
匹配任意數字,等價於[0-9] |
\D |
匹配任意非數字字符 |
\A |
匹配字符串開頭 |
\Z |
匹配字符串結尾,如果存在換行,只匹配到換行前的結束字符串 |
\z |
匹配字符串結尾,如果存在換行,同時還會匹配換行符 |
\G |
匹配最後匹配完成的位置 |
\n |
匹配一個換行符 |
\t |
匹配一個製表符 |
^ |
匹配一行字符串的開頭 |
$ |
匹配一行字符串的結尾 |
. |
匹配任意字符,除了換行符,當re.DOTALL標記被指定時,則可以匹配包括換行符的任意字符 |
[...] |
用來表示一組字符,單獨列出,比如[amk]匹配a、m、k |
[^...] |
不在[]中的字符,比如[^amk]匹配除了a、m、k之外的字符 |
* |
匹配0個或多個表達式 |
+ |
匹配1個或多個表達式 |
? |
匹配0個或1個前面的正則表達式定義的片段,非貪婪方式 |
{n} |
精確匹配n個前面的表達式 |
{n,m} |
匹配n到m次由前面正則表達式定義的片段,貪婪方式 |
a|b |
匹配a或b |
() |
匹配括號內的表達式,也表示一個組 |
常用匹配方法
- match()
向他傳入要匹配的字符串以及正則表達式,可以檢測這個正則表達式是否匹配這個字符串。
match( )方法會嘗試從字符串的起始位置匹配正則表達式,如果匹配就返回成功的結果,否則返回None。
栗子1:
import re
content = 'Hello 123 4567 World_this isa Regex Demo'
result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}',content)
print(result)
print(result.group())
print(result.span())
運行結果如下:
栗子2:匹配目標,提取一部分
可以使用( )括號將想提取的子串括起來。
import re
content = 'Hello 1234567 World_this isa Regex Demo'
result = re.match('^Hello\s(\d+)\sWorld',content)
print(result)
print(result.group())
print(result.group(1))
print(result.span())
運行結果如下:
栗子3:通用匹配.*
.(點)可以匹配任意字符(除換行符),*(星)代表匹配前面的字符無限次,所以它們組合再一起就可以匹配任意字符。
import re
content = 'Hello 123 4567 World_this isa Regex Demo'
result = re.match('^Hello.*Demo$',content)
print(result)
print(result.group())
print(result.span())
運行結果如下:
栗子4:貪婪與非貪婪
使用通配符時,可能有時候匹配到的並不是我們想要的結果。
import re
content = 'Hello 1234567 World_this isa Regex Demo'
result = re.match('^Hello.*(\d+)Demo$',content)
print(result)
print(result.group(1))
運行結果如下:
只得到了7一個數字,?這裏涉及貪婪與非貪婪問題,在貪婪匹配下,.*會匹配儘可能多的字符。.*後面時\d+,也就是至少一個數字,並沒有具體幾個,因此,.*儘可能匹配多的字符,這裏就把123456都匹配了,給\d+只留下了數字7,最後得到的就是7了。
非貪婪匹配寫法爲:.*?
import re
content = 'Hello 1234567 World_this isa Regex Demo'
result = re.match('^Hello.*?(\d+)Demo$',content)
print(result)
print(result.group(1))
運行結果如下:
非貪婪方法匹配儘可能少的字符,當匹配到hello後面的空格字符之後,就不在進行匹配,交給\d+後後面的數字就是1234567了。
栗子5:修飾符
正則表達式可以包含一些可選標誌修飾符來控制匹配的模式。如下:
import re
content ="""Hello 1234567 World_this
isa Regex Demo"""
result = re.match('^Hello.*(\d+)Demo$',content)
print(result.group(1))
運行結果如下:
運行報錯,正則表達式沒有匹配到這個字符串,返回結果爲None。這是因爲.*?不匹配換行符,只要加一個re.S修飾符就行了。
import re
content ="""Hello 1234567 World_this
isa Regex Demo"""
result = re.match('^Hello.*(\d+)Demo$',content,re.S)
print(result.group(1))
一些其他修飾符
修飾符 |
描述 |
re.I |
使匹配對大小寫不敏感 |
re.L |
做本地化識別(locale-aware)匹配 |
re.M |
多行匹配,影響^和$ |
re.S |
使.匹配包含換行符在內的所有字符 |
re.U |
根據Unicode字符集解析字符。 |
re.X |
該標誌通過給予你更靈活的格式以便你將正則表達式寫得更易於理解 |
栗子5:轉義匹配
\進行轉義:
import re
content ="""(百度)www.baidu.com"""
result = re.match('\(百度\)www\.baidu\.com',content)
print(result)
運行結果如下:
2. search( )
match( )方法是從字符串開頭匹配的,一旦開頭不匹配,那麼整個匹配都不成功。search( )方法會掃描整個字符串,然後返回第一個匹配的結果。
3. findall( )
search( )只能返回一個匹配結果,findall( )將返回所有匹配結果。
html ="""
<div id="song-list">
<h2 class="title">經典老歌</h2>
<p class="inrtoduction">
經典老歌列表
</p>
<ul id="list" class="list-group">
<li data-view="2">一路上有你</li>
<li data-veiw="7">
<a href="2.mp3" singer="任賢齊">滄海一聲笑</a>
</li>
<li data-view="4" class="active">
<a href="3.mp3" singer="齊秦">往事隨風</a>
</li>
<li data-view="6"><a href="4.mp3" singer="beyond">光輝歲月</a></li>
<li data-view="5"><a href="5.mp3" singer="陳慧琳">記事本</a></li>
<li data-veiw="5">
<a href="6.mp3" singer="鄧麗君">但願人長久</a>
</li>
</ul>
</div>
"""
results = re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>',html)
print(results)
print(type(results))
for result in results:
print(result)
print(result[0],result[1],result[2])
運行結果如下:
3. sub( )修改文本
re.sub(正則表達式,替換字串,字符串)
4. compile( )
將正則字符串編譯成表達式對象,以便再後面的匹配中複用。
pattern =re.compile(‘\d+’)
如果對你有用,點個贊 手動笑臉(*_*)