1. 程式人生 > >python網路爬蟲學習(三)正則表示式的使用之re.match方法

python網路爬蟲學習(三)正則表示式的使用之re.match方法

一.為什麼要學習正則表示式

很好,我們現在已經能夠寫出獲得網站原始碼的程式了,我們有了第一個問題:如何從雜亂的程式碼中找到我們所需的資訊呢?此時,正則表示式的學習就顯得很有必要了。有人打趣說,當你想到用正則表示式解決一個問題時,你就擁有了兩個問題。從這句話中可以看出正則表示式學習的困難程度,但是為了寫出好的爬蟲,我們必須對其進行學習。

二.正則表示式的語法規則

1.正則表示式的一些註解

(一)貪婪與非貪婪模式

正則表示式通常用於在文字中查詢匹配的字串。Python裡數量詞預設是貪婪的(在少數語言裡也可能是預設非貪婪),總是嘗試匹配儘可能多的字元;非貪婪的則相反,總是嘗試匹配儘可能少的字元。例如:正則表示式”ab*”如果用於查詢”abbbc”,將找到”abbb”。而如果使用非貪婪的數量詞”ab*?”,將找到”a”。

注:我們一般使用非貪婪模式來提取。

(二)反斜槓問題

與大多數程式語言相同,正則表示式裡使用”\”作為轉義字元,這就可能造成反斜槓困擾。假如你需要匹配文字中的字元”\”,那麼使用程式語言表示的正則表示式裡將需要4個反斜槓”\\”:前兩個和後兩個分別用於在程式語言裡轉義成反斜槓,轉換成兩個反斜槓後再在正則表示式裡轉義成一個反斜槓。

Python裡的原生字串很好地解決了這個問題,這個例子中的正則表示式可以使用r”\”表示。同樣,匹配一個數字的”\d”可以寫成r”\d”。有了原生字串,寫出來的表示式更加直觀。

2.python的Re模組

python的Re模組提供對正則表示式的支援,主要用到下列幾種方法

#返回pattern物件
re.compile(string[,flag])  
#以下為匹配所用函式
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,下面對pattern進行介紹。pattern是一個匹配模式,所謂模式,是正則表示式最基本的元素,它們是一組描述字串特徵的字元,是之後用來匹配字元的基礎。那麼如何得到pattern模式呢,我們可以使用re中的compile方法,見程式碼:

pattern=re.compile(r'hello')

我們傳進一個原生字串’hello’,通過compile方法編譯出一個pattern物件,之後我們將用這個物件進行匹配。也就是說之後要做的事就是對要匹配的字串與’hello’作比較。

下面我們看看剛才提到的re模組中的幾種方法

1.re.match(pattern, string[, flags])

這個方法從我們要匹配的字串的頭部開始,當匹配到string的尾部還沒有匹配結束時,返回None;
當匹配過程中出現了無法匹配的字母,返回None。
下面給出一組程式碼來進行具體認識

# -*- coding=utf-8 -*-
import re
pattern=re.compile(r'hello')
result1=re.match(pattern,'hello')
result2=re.match(pattern,'helloc')
result3=re.match(pattern,'helo')
result4=re.match(pattern,'hello world')
if result1:
    print result1.group()
else:
    print '1匹配失敗'
if result2:
    print result2.group()
else:
    print '2失敗'
if result3:
    print result3.group()
else:
    print '3失敗'
if result4:
    print result4.group()
else:
    print '4失敗'

執行結果:

hello
hello
3失敗
hello

對匹配結果進行分析:
1.string與pattern完全相同,成功匹配
2.string雖然多出一個字母,但pattern匹配完成時,匹配成功,後面的c不再匹配。
3.string匹配到最後一個字母時,發現仍然無法完全匹配,匹配失敗。
4.原理同2

下面解釋一下result.group的含義,match是一次匹配的結果,包含很多關於這次匹配的資訊,我們可以通過match提供的屬性和方法讀取到。

下面給出幾個例子對match提供的一些方法加以解釋,程式碼如下

# -*- coding=utf-8 -*-
import re
m=re.match(r'(\w+) (\w+)(?P<char>.*)','hello world!')
print 'm.string',m.string
print 'm.start:',m.start()
print 'm.start:',m.start(2)
print 'm.end:',m.end()
print 'm.end:',m.end(2)
print 'm.pos:',m.pos
print 'm.endpos:',m.endpos
print 'm.group:',m.group(2)
print 'm.groupdict:',m.groupdict()
print 'm.lastgroup:',m.lastgroup
print 'm.lastindex',m.lastindex
print 'm.span:',m.span(2)
print 'm.span',m.span()
print 'm.re:',m.re
print m.expand(r'\2 \1 \3')

執行結果:

m.start: 0
m.start: 0
m.end: 12
m.end: 11
m.pos: 0
m.endpos: 12
m.group: world
m.groupdict: {'char': '!'}
m.lastgroup: char
m.lastindex 3
m.span: (6, 11)
m.span (0, 12)
m.re: <_sre.SRE_Pattern object at 0x02669760>
m.string hello world!
world hello !

結果分析:
1.string是匹配時所用的文字
2.start可以返回指定的組在字串中開始匹配的位置,預設值為0
3.end返回指定的組在字串中開始匹配的位置,預設值為0
4.pos,endpos用於返回起始和終止匹配位置
5.group可以返回指定組的起始匹配位置
6.groupdict返回有別名的組的別名為鍵、以該組截獲的子串為值的字典,沒有別名的組不包含在內。
7.lastgroup返回最後一個被捕獲的分組的別名。如果這個分組沒有別名或者沒有被捕獲的分組,將為None。
8.lastindex返回最後一個分組在文字中的索引
9.span 返回(start(group), end(group)),即該組的起始和終止位置
10.expand可以實現分組之間順序的調整