大家好,我是辰哥~
本文帶大家學(xué)習(xí)正則表達(dá)式,并通過(guò)python代碼舉例講解常用的正則表達(dá)式
最后實(shí)戰(zhàn)爬取小說(shuō)網(wǎng)頁(yè):重點(diǎn)在于爬取的網(wǎng)頁(yè)通過(guò)正則表達(dá)式進(jìn)行解析。
正則表達(dá)式語(yǔ)法
Python的re模塊(正則表達(dá)式)提供各種正則表達(dá)式的匹配操作。在絕大多數(shù)情況下能夠有效地實(shí)現(xiàn)對(duì)復(fù)雜字符串的分析并取出相關(guān)信息。在講解如何實(shí)際應(yīng)用正則表達(dá)式之前,先教大家學(xué)習(xí)并掌握正則表達(dá)式的基本語(yǔ)法(匹配規(guī)則)。
正則表達(dá)式匹配過(guò)程如下:
(1)將定義好的正則表達(dá)式和字符串進(jìn)行比較。
(2)如果每一個(gè)字符串都能匹配,則成功;一旦有匹配不成功的字符則匹配失敗。
正則表達(dá)式規(guī)則
常見(jiàn)規(guī)則

數(shù)量詞匹配規(guī)則

邊界匹配規(guī)則

Re模塊
Python中使用Re庫(kù)去定義的正則表達(dá)式,常用的方法列舉如下:
lpattern對(duì)象
re.compile(string[,flag])
l匹配所用函數(shù)
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對(duì)象是由我們傳入字符串對(duì)象,通過(guò)compile方法生成。利用這個(gè)對(duì)象來(lái)進(jìn)行下一步的匹配。針對(duì)上述列舉的各種正則表達(dá)式匹配規(guī)則和函數(shù),下面通過(guò)Python代碼進(jìn)行舉例講解。
(1) re.match(pattern, string[, flags])
match函數(shù)將會(huì)從String(待匹配的字符串)的開(kāi)頭開(kāi)始,嘗試匹配pattern,一直向后匹配。如果中途匹配pattern成功,則終止匹配,返回匹配結(jié)果。如果無(wú)法匹配或者到字符串末尾還未匹配到,則返回None。
舉例:
#導(dǎo)入re模塊
import re
pattern = re.compile(r'python')
# 使用re.match匹配文本,獲得匹配結(jié)果,無(wú)法匹配時(shí)將返回None
result1 = re.match(pattern,'python')
result2 = re.match(pattern,'pythonn CQC!')
result3 = re.match(pattern,'pthon CQC!')
print(result1)
print(result2)
print(result3)
"""
結(jié)果:
<_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函數(shù)會(huì)掃描整個(gè)string字符串查找匹配,存在的話返回匹配結(jié)果,不存在則返回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)
"""
結(jié)果:
<_sre.SRE_Match object; span=(6, 12), match='python'>
None
"""
(3) re.split(pattern, string[, maxsplit])
split函數(shù)可以按照pattern匹配模式將string字符串分割后返回列表,其中maxsplit參數(shù)可以指定最大分割次數(shù),不指定則將字符串全部分割。
舉例:
import re
#以一位或者多位數(shù)字作為分割間隔
pattern = re.compile(r'\d+')
print(re.split(pattern,'python1java2php3js'))
#只分割兩次
print(re.split(pattern,'python1java2php3js',maxsplit=2))
"""
結(jié)果:
['python', 'java', 'php', 'js']
['python', 'java', 'php3js']
"""
(4) re.findall(pattern, string[, flags])
findall函數(shù)作用是搜索整個(gè)字符串,以列表形式返回全部能匹配的子串。
舉例:
import re
pattern = re.compile(r'\d+')
print(re.findall(pattern,'python1java2php3js2245'))
"""
結(jié)果:
['1', '2', '3', '2245']
"""
(5) re.finditer(pattern, string[, flags])
finditer函數(shù)作用是搜索整個(gè)字符串,返回一個(gè)符合匹配結(jié)果(Match對(duì)象)的迭代器。
舉例:
import re
#以一位或者多位數(shù)字作為搜索條件
pattern = re.compile(r'\d+')
#搜索結(jié)果得到一個(gè)集合,通過(guò)循環(huán)對(duì)集合遍歷輸出
for item in re.finditer(pattern,'python1java2php3js2245'):
print(item.group())
"""
結(jié)果:
1
2
3
2245
"""
(6) re.sub(pattern, repl, string[, count])
先看兩個(gè)例子,然后再解釋這個(gè)sub函數(shù)的作用。
舉例:
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中“數(shù)字123 和9”被python替換。
print(re.sub(pattern2, 'python', 'My number is 123 and my favorite number is 9'))
"""
結(jié)果:
i love the python
My number is python and my favorite number is python
"""
(7) re.subn(pattern, repl, string[, count])
subn可以指定替換次數(shù),不指定則默認(rèn)替換全部。
舉例:
import re
#以一位或者多位數(shù)字作為替換條件
pattern1 = re.compile(r'(\d+)')
#用“python”替換數(shù)字(一位或者多位),最后返回替換結(jié)果和替換次數(shù)
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))
"""
結(jié)果:
('My number is python and my favorite number is python', 2)
('My number is python and my favorite number is 9', 1)
"""
實(shí)戰(zhàn)
需求:提取小說(shuō)章節(jié)正文和標(biāo)題
本節(jié)通過(guò)實(shí)戰(zhàn)案例來(lái)講解正則表達(dá)式的應(yīng)用。案例目的是:提取小說(shuō)章節(jié)內(nèi)容。步驟是先采集到每一章小說(shuō)正文內(nèi)容網(wǎng)頁(yè)源碼,然后通過(guò)正則表達(dá)式將里面的正文提取出來(lái)。
這里爬取小說(shuō) 第一章 北靈院,用正則表達(dá)式提取小說(shuō)章節(jié)正文和標(biāo)題
目標(biāo)鏈接:http://book.chenlove.cn/book/12242/39a44ff6dd27f.html
頁(yè)面如下:

分析網(wǎng)頁(yè)源碼:

可以看到章節(jié)標(biāo)題在h3標(biāo)簽中,其class為j_chapterName;正文內(nèi)容在p標(biāo)簽中,清楚這些之后,下面開(kāi)始編寫(xiě)代碼請(qǐng)求網(wǎng)頁(yè)源碼,并編寫(xiě)正則表達(dá)式去提取標(biāo)題和正文。
完整代碼如下:
import requests
import re
import json
# 設(shè)置代理服務(wù)器
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'
}
#請(qǐng)求連接
url = "http://book.chenlove.cn/book/12242/39a44ff6dd27f.html"
response = requests.get(url, headers=headers)
if response.status_code == 200:
# 轉(zhuǎn)化為utf-8格式,不加這條語(yǔ)句,輸出爬取的信息為亂碼
response.encoding = 'utf8'
#獲取到源碼
html = response.text
# 正則表達(dá)式解析小說(shuō)章節(jié)標(biāo)題
pattern1 = re.compile('<h3>(.+)</h3>')
title = re.findall(pattern1, html)[0]
#正則表達(dá)式解析小說(shuō)章節(jié)正文內(nèi)容
text = re.findall(r"<p>(.*?)</p>", html,re.S)[2:-1][0].split("</div>")[0]
# 打印輸出
print(title)
print(text)
"""
結(jié)果:
第一章 北靈院
烈日如炎,灼熱的陽(yáng)光從天空上傾灑下來(lái),令得整片大地都是處于一片蒸騰之中,楊柳微垂,......
"""
可以看到第一章的標(biāo)題和正文已經(jīng)成功提取出來(lái)了,因?yàn)檎膬?nèi)容很長(zhǎng),這里僅展示部分。
最后
本文匯總正則表達(dá)式常用的基本語(yǔ)法,并結(jié)合Python進(jìn)行舉例演示
最后實(shí)戰(zhàn)講解正則表達(dá)式在爬蟲(chóng)中的應(yīng)用。