正規表達式是很通用的一套規則,而本文是基于python的re模型的實作,來講解正規表達式的文法。常見的正規表達式如圖:
我們講講python中re子產品常用的方法。1、re.match()(其實,最好用re.search(),能完全替換re.match())
re.match()方法嘗試從第一個起始位置比對一個模型,如果不是起始位置比對成功的化,傳回none
1.1、正常比對
content = 'Hello 123 4567 World_This is a Regex Demo'
result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}.*Demo$', content)
print(result)
print(result.group()) #group()方法傳回字元串
1.2、泛比對
content = 'Hello 123 4567 World_This is a Regex Demo'
result = re.match('^Hello.*Demo$$', content)
print(result.group())
1.3、比對目标
content = 'Hello 123 4567 World_This is a Regex Demo'
result = re.match('.*(\d{3}\s\d{4}).*', content) #小括号()表示要傳回的目标
print(result.group(1))
1.4、貪婪比對,比對盡可能多的字元
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^He.*(\d+).*$', content)
print(result.group(1))
1.5、非貪婪比對,比對盡可能少的字元,例如看到後面是比對數字的規則了,就停止前面的比對
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^He.*?(\d+).*$', content)
print(result.group(1))
1.6、比對模式
content = '''Hello 1234567 World_This
is a Regex Demo
'''
#如果不使用re.S參數,則隻在每一行内進行比對,如果一行沒有,就換下一行重#新開始,不會跨行。而使用re.S參數以後,正規表達式會将這個字元串作為一個整#體,将“\n”當做一個普通的字元加入到這個字元串中,在整體中進行比對。
result = re.match('^He.*?(\d+).*?Demo$', content, re.S)
print(result.group(1))
'''
####1.7、轉義
```python
#盡量使用泛比對、使用括号得到比對目标、盡量使用非貪婪模型、有換行符就是要re.S
content = 'price is $5.00'
result = re.match('price is \$5\.00', content)
print(result)
2、re.search()
re.search()掃描整個字元串并傳回第一個成功的比對,能用search不用match。
#盡量使用泛比對、使用括号得到比對目标、盡量使用非貪婪模型、有換行符就是要re.S
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('Hello.*?(\d+).*', content)
print(result.group(1))
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))
3、re.findall()
re.findall()以清單的形式傳回全部能比對的子串
results = re.findall('<a.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>', html, re.S)
print(results)
4、re.sub()
re.sub()替換字元串中每一個比對的子串後傳回替換後的字元串
content = 'Hello 1234567 World_This is a Regex Demo'
content = re.sub('\d+', 'replacement', content)
print(content)
5、re.compile()
re.compile()将正則字元串編譯成正規表達式對象,以便于複用該比對模式
content = 'Hello 1234567 World_This is a Regex Demo'
pattern = re.compile('Hello.*Demo')
result = re.match(pattern, content)
print(result)
#下面示範一個取整個文本一段文字的例子
content = '''<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('<ul.*?</ul>', content, re.S)
print(result.group())
6、實戰演練
import requests
import re
content = requests.get('https://book.douban.com/').text
#為什麼要先截出來一部分,因為如果整個用pattern比對太慢了。。
content = re.search('<ul class="list-col list-col5 list-express slide-item">.*?</ul>', content, re.S).group()
pattern = re.compile('<li.*?cover.*?href="(.*?)".*?title="(.*?)".*?more-meta.*?author">(.*?)</span>.*?year">(.*?)</span>.*?</li>', re.S)
results = re.findall(pattern, content)
for result in results:
url, name, author, date = result
author = re.sub('\s', '', author)
date = re.sub('\s', '', date)
print(url, name, author, date)
結果如下: