大家好,我是辰哥~
本文帶大家學習正則表達式,并通過python代碼舉例講解常用的正則表達式
最后實戰爬取小說網頁:重點在于爬取的網頁通過正則表達式進行解析。
正則表達式語法
Python的re模塊(正則表達式)提供各種正則表達式的匹配操作。在絕大多數情況下能夠有效地實現對復雜字符串的分析并取出相關信息。在講解如何實際應用正則表達式之前,先教大家學習并掌握正則表達式的基本語法(匹配規則)。
正則表達式匹配過程如下:
(1)將定義好的正則表達式和字符串進行比較。
(2)如果每一個字符串都能匹配,則成功;一旦有匹配不成功的字符則匹配失敗。
正則表達式規則
常見規則
數量詞匹配規則
邊界匹配規則
Re模塊
Python中使用Re庫去定義的正則表達式,常用的方法列舉如下:
lpattern對象
re.compile(string[,flag])
l匹配所用函數
re.match(pattern, string[, flags])
re.search(pattern, string[, flags])
re.split(pattern, string[, maxsplit])
re.findall(pattern, string[, flags])
re.finditer(pattern, string[, flags])
re.sub(pattern, repl, string[, count])
re.subn(pattern, repl, string[, count])
其中pattern對象是由我們傳入字符串對象,通過compile方法生成。利用這個對象來進行下一步的匹配。針對上述列舉的各種正則表達式匹配規則和函數,下面通過Python代碼進行舉例講解。
(1) re.match(pattern, string[, flags])
match函數將會從String(待匹配的字符串)的開頭開始,嘗試匹配pattern,一直向后匹配。如果中途匹配pattern成功,則終止匹配,返回匹配結果。如果無法匹配或者到字符串末尾還未匹配到,則返回None。
舉例:
#導入re模塊
import re
pattern = re.compile(r'python')
# 使用re.match匹配文本,獲得匹配結果,無法匹配時將返回None
result1 = re.match(pattern,'python')
result2 = re.match(pattern,'pythonn CQC!')
result3 = re.match(pattern,'pthon CQC!')
print(result1)
print(result2)
print(result3)
"""
結果:
<_sre.SRE_Match object; span=(0, 6), match='python'>
<_sre.SRE_Match object; span=(0, 6), match='python'>
None
"""
(2) re.search(pattern, string[, flags])
Search函數會掃描整個string字符串查找匹配,存在的話返回匹配結果,不存在則返回None。
舉例:
import re
pattern = re.compile(r'python')
#從“hello pythonnnnn!”中匹配“python”
result1 = re.search(pattern,'hello pythonnnnn!')
#從“hello pyhon!”中匹配“python”
result2 = re.search(pattern,'hello pyhon!')
print(result1)
print(result2)
"""
結果:
<_sre.SRE_Match object; span=(6, 12), match='python'>
None
"""
(3) re.split(pattern, string[, maxsplit])
split函數可以按照pattern匹配模式將string字符串分割后返回列表,其中maxsplit參數可以指定最大分割次數,不指定則將字符串全部分割。
舉例:
import re
#以一位或者多位數字作為分割間隔
pattern = re.compile(r'\d+')
print(re.split(pattern,'python1java2php3js'))
#只分割兩次
print(re.split(pattern,'python1java2php3js',maxsplit=2))
"""
結果:
['python', 'java', 'php', 'js']
['python', 'java', 'php3js']
"""
(4) re.findall(pattern, string[, flags])
findall函數作用是搜索整個字符串,以列表形式返回全部能匹配的子串。
舉例:
import re
pattern = re.compile(r'\d+')
print(re.findall(pattern,'python1java2php3js2245'))
"""
結果:
['1', '2', '3', '2245']
"""
(5) re.finditer(pattern, string[, flags])
finditer函數作用是搜索整個字符串,返回一個符合匹配結果(Match對象)的迭代器。
舉例:
import re
#以一位或者多位數字作為搜索條件
pattern = re.compile(r'\d+')
#搜索結果得到一個集合,通過循環對集合遍歷輸出
for item in re.finditer(pattern,'python1java2php3js2245'):
print(item.group())
"""
結果:
1
2
3
2245
"""
(6) re.sub(pattern, repl, string[, count])
先看兩個例子,然后再解釋這個sub函數的作用。
舉例:
import re
pattern1 = re.compile(r'music')
#例1中“i love the music”里的music替換成python
print(re.sub(pattern1, 'python', 'i love the music'))
pattern2 = re.compile(r'(\d+)')
#例2中“數字123 和9”被python替換。
print(re.sub(pattern2, 'python', 'My number is 123 and my favorite number is 9'))
"""
結果:
i love the python
My number is python and my favorite number is python
"""
(7) re.subn(pattern, repl, string[, count])
subn可以指定替換次數,不指定則默認替換全部。
舉例:
import re
#以一位或者多位數字作為替換條件
pattern1 = re.compile(r'(\d+)')
#用“python”替換數字(一位或者多位),最后返回替換結果和替換次數
print(re.subn(pattern1, 'python', 'My number is 123 and my favorite number is 9'))
pattern2 = re.compile(r'(\d+)')
print(re.subn(pattern2, 'python', 'My number is 123 and my favorite number is 9',1))
"""
結果:
('My number is python and my favorite number is python', 2)
('My number is python and my favorite number is 9', 1)
"""
實戰
需求:提取小說章節正文和標題
本節通過實戰案例來講解正則表達式的應用。案例目的是:提取小說章節內容。步驟是先采集到每一章小說正文內容網頁源碼,然后通過正則表達式將里面的正文提取出來。
這里爬取小說 第一章 北靈院,用正則表達式提取小說章節正文和標題
目標鏈接:http://book.chenlove.cn/book/12242/39a44ff6dd27f.html
頁面如下:
分析網頁源碼:
可以看到章節標題在h3標簽中,其class為j_chapterName;正文內容在p標簽中,清楚這些之后,下面開始編寫代碼請求網頁源碼,并編寫正則表達式去提取標題和正文。
完整代碼如下:
import requests
import re
import json
# 設置代理服務器
headers = {
'User_Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'
}
#請求連接
url = "http://book.chenlove.cn/book/12242/39a44ff6dd27f.html"
response = requests.get(url, headers=headers)
if response.status_code == 200:
# 轉化為utf-8格式,不加這條語句,輸出爬取的信息為亂碼
response.encoding = 'utf8'
#獲取到源碼
html = response.text
# 正則表達式解析小說章節標題
pattern1 = re.compile('<h3>(.+)</h3>')
title = re.findall(pattern1, html)[0]
#正則表達式解析小說章節正文內容
text = re.findall(r"<p>(.*?)</p>", html,re.S)[2:-1][0].split("</div>")[0]
# 打印輸出
print(title)
print(text)
"""
結果:
第一章 北靈院
烈日如炎,灼熱的陽光從天空上傾灑下來,令得整片大地都是處于一片蒸騰之中,楊柳微垂,......
"""
可以看到第一章的標題和正文已經成功提取出來了,因為正文內容很長,這里僅展示部分。
最后
本文匯總正則表達式常用的基本語法,并結合Python進行舉例演示
最后實戰講解正則表達式在爬蟲中的應用。