#--Name: 正則
0x00 什麼是正則表達式?
正則表達式是對字符串操作的一種邏輯公式,就是用事先定義好的一些特定字符,
以及這些特定字符的組合,組成一個 "規則字符串",這個 "規則字符串"用來
表達對字符串的一種過濾邏輯
特別需要注意的是:
正則表達式非Python獨有,re模塊實現
0x01 在線正則表達式測試
http://tool.oschina.net/regex/
0x02 python中re模塊 match 方法
#re.match 嘗試從字符串的起始位置匹配一個模式,如果不是起始位置匹配成功的話,match()就會返回none
re.match(pattern,string,flags=0)
0x03 re.match的相關實例
#最常規的匹配
import re
content = 'Hello 123 4567 World_This is a Regex Demo'
print(len(content))
result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}.*Demo$',content)
print(result)
print(result.group())
print(result.span())
#泛匹配 如果上面的匹配你覺得太過於冗長,那麼可是使用泛匹配 ' .* '
import re
content = 'Hello 123 4567 World_This is a Regex Demo'
result = re.match('^Hello.*Demo$',content)
print(result)
print(result.group())
print(result.span())
#匹配目標
import re
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^Hello\s(\d+)\sWorld.*Demo$',content)
print(result)
print(result.group()) # 打印全部
print(result.group(1)) # 打印第1個括號內的匹配結果,如果表達式中有多個括號,第一個括號內的結果就是group(1)
#第二個括號內的結果就是group(2),以此類推
print(result.span())
#貪婪匹配 使用 ' .* ' 儘可能匹配多的字符
import re
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^He.*(\d+).*Demo$',content)
print(result.group(1))
#非貪婪匹配 使用 ' .*? ' 儘可能匹配少的字符
import re
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^He.*?(\d+).*Demo$',content)
print(result.group(1))
#匹配模式 .* 除了換行符之外,可以匹配任意字符,需要匹配換行時,則需要指定 ' re.S ' 模式
import re
content = '''Hello 1234567 World_This
is a Regex Demo
'''
result = re.match('^He.*?(\d+).*?Demo$',content,re.S)
print(result.group(1))
#轉義
#用例1: 在不轉意的情況下
import re
content = 'price is $5.00'
result = re.match('price is $5.00',content)
print(result)
#用例2: 加入轉義
import re
content = 'price is $5.00'
result = re.match('price is \$5\.00',content)
print(result)
#總結: 在實際的使用中 儘量使用泛匹配, 使用括號得到匹配目標, 儘量使用非貪婪模式, 有換行符就用 re.S
0x04 re.search 使用實例
#re.search 掃描整個字符串並返回第一個成功的匹配
#用例1: 使用re.match方法
import re
content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
result = re.match('Hello.*?(\d+).*?Demo',content)
print(result)
#用例2: 使用re.search方法
import re
content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
result = re.search('Hello.*?(\d+).*?Demo',content)
print(result)
print(result.group(1))
#總結: 爲了匹配方便,在能用search方法的場景下,就不用match
0x05 匹配演練
#匹配1: 匹配 有active的li標籤
import re
html = '''<div id='songs-list'>
<h2 class='title'>經典老歌</h2>
<p class='introduction'>
經典老歌列表
</p>
<ul id='list' class='list-group'>
<li data-view='2'>一路上有你</li>
<li data-view='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-view='5'>
<a href='/6.mp3' singer='鄧麗君'><i class='fa fa-user'></i>但願人長久</a>
</li>
</ul>
</div>'''
result = re.search("<li.*?active.*?singer='(.*?)'>(.*?)</a>", html, re.S)
if result:
print(result.group(1), result.group(2))
#匹配: 匹配第二個li標籤
import re
html = '''<div id='songs-list'>
<h2 class='title'>經典老歌</h2>
<p class='introduction'>
經典老歌列表
</p>
<ul id='list' class='list-group'>
<li data-view='2'>一路上有你</li>
<li data-view='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-view='5'>
<a href='/6.mp3' singer='鄧麗君'><i class='fa fa-user'></i>但願人長久</a>
</li>
</ul>
</div>'''
result = re.search("<li.*?singer='(.*?)'>(.*?)</a>", html, re.S)
if result:
print(result.group(1), result.group(2))
#匹配: 匹配有完整歌曲信息的第三個li標籤
import re
html = '''<div id='songs-list'>
<h2 class='title'>經典老歌</h2>
<p class='introduction'>
經典老歌列表
</p>
<ul id='list' class='list-group'>
<li data-view='2'>一路上有你</li>
<li data-view='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-view='5'>
<a href='/6.mp3' singer='鄧麗君'><i class='fa fa-user'></i>但願人長久</a>
</li>
</ul>
</div>'''
result = re.search("<li.*?singer='(.*?)'>(.*?)</a>", html)
if result:
print(result.group(1), result.group(2))
0x06 re.findall 使用實例
搜索字符串,以列表形式返回全部能匹配的子串
查詢符合條件的所有結果
#匹配: 匹配出所有的歌曲鏈接 歌手名稱 歌曲名稱
import re
html = '''<div id='songs-list'>
<h2 class='title'>經典老歌</h2>
<p class='introduction'>
經典老歌列表
</p>
<ul id='list' class='list-group'>
<li data-view='2'>一路上有你</li>
<li data-view='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-view='5'>
<a href='/6.mp3' singer='鄧麗君'>但願人長久</a>
</li>
</ul>
</div>'''
results = re.findall("<li.*?href='(.*?)'.*?singer='(.*?)'>(.*?)</a>",html,re.S)
print(results)
print(type(results))
for result in results:
print(result)
#匹配: 匹配出所有有完整信息的歌曲名稱
import re
html = '''<div id='songs-list'>
<h2 class='title'>經典老歌</h2>
<p class='introduction'>
經典老歌列表
</p>
<ul id='list' class='list-group'>
<li data-view='2'>一路上有你</li>
<li data-view='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-view='5'>
<a href='/6.mp3' singer='鄧麗君'>但願人長久</a>
</li>
</ul>
</div>'''
results = re.findall("<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>",html, re.S)
print(results)
for result in results:
print(result[1])
0x07 re.sub
替換字符串中每一個匹配的字串後,返回替換後的字符串
#用例1: 把其中的數字替換掉
import re
content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
result = re.sub('\d+','',content)
print(result)
#用例2: 把其中的數字替換成指定內容
import re
content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
result = re.sub('\d+','這裏以前是數字',content)
print(result)
#用例3: 被替換中的內容包含原內容的情況
import re
content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
result = re.sub('(\d+)',r'\1 8910',content)
#值得注意的是,由於第二個參數中插入了轉義字符'\',爲了保證它的內容是原生內容,前面用了個 'r'
#並且,前面的條件加了個小括號, 也就是 group(1)的意思
print(result)
#我們先把<a>標籤替換掉,再用findall方法提取數據
#發現數據中存在換行符 \n
#我們再用 strip()方法去掉換行符
import re
html = '''<div id='songs-list'>
<h2 class='title'>經典老歌</h2>
<p class='introduction'>
經典老歌列表
</p>
<ul id='list' class='list-group'>
<li data-view='2'>一路上有你</li>
<li data-view='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-view='5'>
<a href='/6.mp3' singer='鄧麗君'>但願人長久</a>
</li>
</ul>
</div>'''
html = re.sub("<a.*?>|</a>",'',html)
print(html)
results = re.findall("<li.*?>(.*?)</li>",html,re.S)
print(results)
for result in results:
print(result.strip())
0x08 re.compile,把字符串編譯成正則表達式對象
#將一個正則表達式串編譯成正則對象,以便於複用該匹配模式
#用例1:
import re
content = '''Hello 1234567 World_This
is a Regex Demo'''
pattern = re.compile('Hello.*Demo',re.S)
#result = re.match('Hello.*Demo',content,re.S)
#可以嘗試上面的寫法和下面的寫法用法是一樣的
#爲什麼要這麼做? 這是爲了便於以後的代碼複用
result = re.match(pattern,content)
print(result)
0x09 實戰練習
#綜合使用之前的方法 做一個豆瓣圖書的爬取
import requests
import re
#該實例獲取豆瓣圖書的出版信息等等
#請寫代碼實現,獲取鏈接url,書名,作者,出版日期,出版社,簡介
#換行符號請使用 re.sub方法來實現
#要使用re.compile