Python3 爬虫学习笔记 C06 【正则表达式】
Python3 爬蟲學習筆記第六章 —— 【正則表達式】
文章目錄
- 【6.1】關于正則表達式
- 【6.2】re.match() 方法
- 【6.2.1】提取內容
- 【6.2.2】通用匹配
- 【6.2.3】貪婪匹配
- 【6.2.4】非貪婪匹配
- 【6.2.5】轉義匹配
- 【6.2.6】修飾符
- 【6.3】re.search() 方法
- 【6.4】re.findall() 方法
- 【6.5】re.sub() 方法
- 【6.5】re.compile() 方法
【6.1】關于正則表達式
正則表達式是對字符串操作的一種邏輯公式,用定義好的特定字符和這些特定字符的組合組成一個規則字符串,這個規則字符串原來表達對字符串的一種過濾邏輯,從而實現字符串的檢索、替換、匹配驗證等。Python 的 re 庫提供了整個正則表達式的實現,包含五種方法:match、search、findall、sub、compile
常用的匹配規則:
| \w | 匹配字母、數字及下劃線 |
| \W | 匹配不是字母、數字及下劃線的字符 |
| \s | 匹配任意空白字符,等價于 [\t\n\r\f] |
| \S | 匹配任意非空字符 |
| \d | 匹配任意數字,等價于 [0-9] |
| \D | 匹配任意非數字的字符 |
| \A | 匹配字符串開頭 |
| \z | 匹配字符串結尾,如果存在換行,同時還會匹配換行符 |
| \Z | 匹配字符串結尾,如果存在換行,只匹配到換行前的結束字符串 |
| \G | 匹配最后匹配完成的位置 |
| \n | 匹配一個換行符 |
| \t | 匹配一個制表符 |
| ^ | 匹配一行字符串的開頭 |
| $ | 匹配一行字符串的結尾 |
| . | 匹配任意字符,除了換行符,當 re.DOTALL 標記被指定時,則可以匹配包括換行符的任意字符 |
| […] | 用來表示一組字符,單獨列出,比如 [amk] 匹配 a、m 或 k |
| [^…] | 不在 [] 中的字符,比如 匹配除了 a、b、c 之外的字符 |
| * | 匹配 0 個或多個表達式 |
| + | 匹配 1 個或多個表達式 |
| ? | 匹配 0 個或 1 個前面的正則表達式定義的片段,非貪婪方式 |
| {n} | 精確匹配 n 個前面的表達式 |
| {n, m} | 匹配 n 到 m 次由前面正則表達式定義的片段,貪婪方式 |
| a|b | 匹配 a 或 b |
| ( ) | 匹配括號內的表達式,也表示一個組 |
【6.2】re.match() 方法
match() 方法會嘗試從字符串的起始位置匹配正則表達式,如果匹配,就返回匹配成功的結果;如果不匹配,就返回 None,在 match() 方法中,第一個參數傳入正則表達式,第二個參數傳入要匹配的字符串。
import recontent = 'This is a Demo_123 4567_I Love China' print(len(content)) result = re.match('^This\s\w\w\s\w\s\w{5}\d{3}\s\w{6}', content) print(result) print(result.group()) print(result.span())輸出結果:
36 <_sre.SRE_Match object; span=(0, 25), match='This is a Demo_123 4567_I'> This is a Demo_123 4567_I (0, 25)打印 result 結果是 SRE_Match 對象,表明匹配成功。SRE_Match 對象有兩種方法:group() 方法可以輸出匹配到的內容;span() 方法可以輸出匹配的范圍。
【6.2.1】提取內容
使用括號將想提取的子字符串括起來。括號實際上標記了一個子表達式的開始和結束位置,被標記的每個子表達式會依次對應每一個分組,調用 group() 方法傳入分組的索引即可獲取提取的結果。
import recontent = 'This is a Demo_123 4567_I Love China' result = re.match('^This\s\w\w\s\w\s(\w{5})\d{3}\s\w{6}', content) print(result) print(result.group()) print(result.group(1)) print(result.span())輸出結果:
<_sre.SRE_Match object; span=(0, 25), match='This is a Demo_123 4567_I'> This is a Demo_123 4567_I Demo_ (0, 25)【6.2.2】通用匹配
如果每個字符都用都用一個符號來匹配的話就顯得比較麻煩,可以用 .*來匹配,. 可以匹配除換行符外的任意字符,* 代表匹配前面的字符無限次。
import recontent = 'This is a Demo_123 4567_I Love China' result = re.match('^This.*China$', content) print(result) print(result.group()) print(result.span())輸出結果:
<_sre.SRE_Match object; span=(0, 36), match='This is a Demo_123 4567_I Love China'> This is a Demo_123 4567_I Love China (0, 36)【6.2.3】貪婪匹配
import recontent = 'This is a Demo_1234567_I Love China' result = re.match('^This.*(\d+).*China$', content) print(result) print(result.group()) print(result.group(1)) print(result.span())輸出結果:
<_sre.SRE_Match object; span=(0, 35), match='This is a Demo_1234567_I Love China'> This is a Demo_1234567_I Love China 7 (0, 35).* 為貪婪匹配,會匹配盡可能多的字符,所以 \d+ 只會匹配到最后一個數字,而不是所有的數字
【6.2.4】非貪婪匹配
import recontent = 'This is a Demo_1234567_I Love China' result = re.match('^This.*?(\d+).*China$', content) print(result) print(result.group()) print(result.group(1)) print(result.span())輸出結果:
<_sre.SRE_Match object; span=(0, 35), match='This is a Demo_1234567_I Love China'> This is a Demo_1234567_I Love China 1234567 (0, 35).*? 為非貪婪匹配,會匹配盡可能少的字符,所以 \d+ 會匹配到所有的數字
【6.2.5】轉義匹配
當遇到用于正則匹配模式的特殊字符時,在前面加反斜線轉義一下即可。例如 . 可以用 \. 來匹配:
import recontent = '(博客)www.itrhx.com' result = re.match('\(博客\)www\.itrhx\.com', content) print(result) print(result.group())輸出結果:
<_sre.SRE_Match object; span=(0, 17), match='(博客)www.itrhx.com'> (博客)www.itrhx.com【6.2.6】修飾符
修飾符用來解決換行、大小寫等問題,較為常用的有 re.S 和 re.I。
| re.S | 使 . 匹配包括換行在內的所有字符 |
| re.I | 使匹配對大小寫不敏感 |
| re.L | 做本地化識別(locale-aware)匹配 |
| re.M | 多行匹配,影響 ^ 和 $ |
| re.U | 根據 Unicode 字符集解析字符。這個標志影響 \w、\W、\b 和 \B |
| re.X | 該標志通過給予你更靈活的格式以便你將正則表達式寫得更易于理解 |
示例:
import recontent = '''This is a Demo_1234567_I Love China''' result = re.match('^This.*?(\d+).*China$', content) print(result) print(result.group()) print(result.group(1)) print(result.span())示例中 content 字段進行了換行處理,如果沒有修飾符,就會報錯:
Traceback (most recent call last): NoneFile "F:/PycharmProjects/Python3爬蟲/test.py", line 7, in <module>print(result.group()) AttributeError: 'NoneType' object has no attribute 'group'添加 re.S 修飾符后即可匹配成功:
import recontent = '''This is a Demo_1234567_I Love China''' result = re.match('^This.*?(\d+).*China$', content, re.S) print(result) print(result.group()) print(result.group(1)) print(result.span())輸出結果:
<_sre.SRE_Match object; span=(0, 46), match='This is a Demo_1234567\n _I Love China'> This is a Demo_1234567_I Love China 1234567 (0, 46)【6.3】re.search() 方法
match() 方法只能從字符串的開頭開始匹配,一旦開頭不匹配,那么整個匹配就失敗了,match() 方法更適合用來檢測某個字符串是否符合某個正則表達式的規則,而 search() 方法則會掃描整個字符串并返回第一個成功的匹配
import recontent = 'This is a Demo_1234567_I Love China' result = re.search('a.*?(\d{5})', content) print(result) print(result.group(1))輸出結果:
<_sre.SRE_Match object; span=(8, 20), match='a Demo_12345'> 12345【6.4】re.findall() 方法
search() 方法則會掃描整個字符串,但是返回的是第一個成功的匹配,而 findall() 方法將會返回所有成功的匹配
import rehtml = '''<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="安與騎兵"> 紅山果 </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)print(result[0], result[1], result[2])輸出結果:
[('/2.mp3', '趙雷', ' 理想 '), ('/3.mp3', '許巍', ' 像風一樣自由 '), ('/4.mp3', '安與騎兵', ' 紅山果 '), ('/5.mp3', '薛之謙', ' 意外 '), ('/6.mp3', '馬頔', ' 但南山南 ')] <class 'list'> ('/2.mp3', '趙雷', ' 理想 ') /2.mp3 趙雷 理想 ('/3.mp3', '許巍', ' 像風一樣自由 ') /3.mp3 許巍 像風一樣自由 ('/4.mp3', '安與騎兵', ' 紅山果 ') /4.mp3 安與騎兵 紅山果 ('/5.mp3', '薛之謙', ' 意外 ') /5.mp3 薛之謙 意外 ('/6.mp3', '馬頔', ' 但南山南 ') /6.mp3 馬頔 但南山南【6.5】re.sub() 方法
與字符串的 replace() 方法類似,sub() 方法可以對文本進行修改,sub() 方法第一個參數為匹配對象,第二個參數為替換成的字符串,如果要去掉匹配對象的話,可以賦值為空,第三個參數為原來的字符串
import recontent = '87dsf4as2w4jh1k4kdl4' result = re.sub('\d+', '', content) print(result)輸出結果:
dsfaswjhkkdl【6.5】re.compile() 方法
compile() 方法可以將正則字符串編譯成正則表達式對象,以便在后面的匹配中復用
import recontent1 = '北京時間:2019-08-24 18:30' content2 = '倫敦時間:2019-08-24 11:30' content3 = '巴黎時間:2019-08-24 12:30' content4 = '外星時間:9019-99-66 50:30' pattern = re.compile('\d{2}:\d{2}') result1 = re.sub(pattern, '', content1) result2 = re.sub(pattern, '', content2) result3 = re.sub(pattern, '', content3) result4 = re.sub(pattern, '', content4) print(result1, result2, result3, result4)利用 compile() 方法將正則表達式編譯成一個正則表達式對象,以便復用,然后用 sub() 方法去掉具體時間
輸出結果:
總結
以上是生活随笔為你收集整理的Python3 爬虫学习笔记 C06 【正则表达式】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 霸气!红旗LS7双色版外观亮相:劳斯莱斯
- 下一篇: 历史会重演?今年的我国,还会像2008年