1. 程式人生 > >python進階(爬蟲正則表示式)

python進階(爬蟲正則表示式)

一、正則表示式的基本知識:

1、正則表示式是一種高度專業化的程式語言,並不是只在python語言中存在,而python需要插入 re 模組才能使用 正則表示式。

2、正則表示式只能處理字串,用於模糊匹配。

3、正則表示式的區間是閉區間。

二、正則表示式組成:

               1、正則表示式由字符集[...]、量詞(* + ?{ })、邊界(^ $)、邏輯( | )、re模組的函式五部分組成。

               2、一個字符集(\d  \w 這些也屬於字符集,它們不需要用 [  ] 包裹 )不論有多複雜,在沒有量詞的情況下,只代表一個字元

import re
print(re.findall('\d','234da'))       ['2', '3', '4', '5']
print(re.findall('\d\d','234da'))     ['23', '45']   相當於兩個字符集

三、字元組([....]):

        ①一個字元組只能匹配一個字元,它是一個閉區間。

        ②字符集內特殊意義的字元大都會失去原有的含義,型別轉義字元   \ 。(轉義字元 \ 和 小括號不會失去含義)

        ④字元組中的範圍可以相連:[0-9a-zA-Z+_-],中間不需要加逗號分隔,也不要用[[0-9][a-z][A-Z]+_-]這種中間套[]的方式。

        ⑤字元組中元素見得關係是或的關係,例:[^abc] [^a|b|c]        

        ⑥   ^   如果在[  ]內部的開頭,代表 非 ,若果在正則表示式開頭,代表匹配必須是   行頭。

常見的字元:

(1)直接匹配:

              匹配表示式就是字元本身。

import re
print(re.findall('ab','++=_-aabjab_-=jk'))

['ab', 'ab']

(2)通配字元( . ):

            能夠匹配除了換行符(\n)以外的所有字元。

import re
print(re.findall('.','+=_-a | \n *'))    # 包括 空格

['+', '=', '_', '-', 'a', ' ', '|', ' ', ' ', '*']

(3)轉義字元(\):

import re
print('換行符\n換行了')           轉義字元在print語句中的用法。
print('轉義符\\n轉義了')                  轉義了 \n
print(r'raw方法將字串\n轉化為元字元!')    \n失去意義,字串前加上 r,就會將轉化為無意義的元字元(raw)。

                 #  換行符可以直接匹配
print(re.findall('\n','jadj \n ajfkfjjjfj'))
print(re.findall('\\n','jadj \n ajfkfjjjfj')
                # 需要轉義(一些在正則表示式中有意義的字元 * ? + 等)
print(re.findall('\+','jad + ajfkfjjjfj'))
print(re.findall('[+]','jad + ajfkfjjjfj'))       []可以使特殊字元沒有意義。
print(re.findall('\.','jadj . ajfkfjjjfj'))
print(re.findall('[.]','jadj . ajfkfjjjfj'))
print(re.findall('\[\]','jadj . ajfkfjjj[]fj'))    結果: ['[]'],[]在正則中有意義,需要轉義
print(re.findall('\(\)','jadj . ajfkfjjj()fj'))   結果:['()']



換行符
換行了
轉義符\n轉義了
raw方法將字串\n轉化為元字元!
['\n']
['\n']
['+']
['+']
['.']
['.']

②轉義字元(\)匹配方法:

特殊:
print(re.findall('','ajd'))      結果:['', '', '', '']
                    
                    轉義字元本身匹配 (未解決問題)
print('ajdjca\\cjijfj')       #      ajdjca\cjijfj
print('ajdjca\cjijfj')         #     ajdjca\cjijfj
print(re.findall('a\\\c','ajdjca\cjijfj'))    結果:['a\\c']
print(re.findall('a\\c','ajdjca\cjijfj'))   報錯

③常用方法:

④易錯:

1、      字符集元素之間是  或  的關係。
print(re.findall('[^abc]','123adbc'))     
print(re.findall('[^(a|b|c)]','123adbc'))

['1', '2', '3', 'd']
['1', '2', '3', 'd']
2、     字元組中的範圍 直接相連
print(re.findall('[0-9a-c]','12zafc'))
print(re.findall('[[0-9][a-c]]','12zafc'))     
print(re.findall('[]]]]','12zafc[0]]]]'))

['1', '2', 'a', 'c']
[]
[']]]']

3、字元:

                             這種字元可以理解為  字符集[...]的簡寫方式,在沒有量詞的情況下

           

                            可以巢狀在字元組中。

                     一個\d或[...]代表一個字元
import re
print(re.findall('[\d]','16hgdh6'))
print(re.findall('\d','16hgdh6'))
print(re.findall('\d\w','16hgdh6'))        

['1', '6', '6']
['1', '6', '6']
['16']

4、中文字元:

                                                 

                      一個字符集只能匹配一箇中文字元。 \w 也包括中文字元。

 

四、數量詞:

             

                  ①  數量詞只增加其前面 一個字符集的次數,如果要重複多個字符集,應當加入分組(),加入分組以後,findall只會列印分組的內容。如下:

                  ② 預設情況是貪婪匹配。

import re
print(re.findall('ab*','abbbbbbbbbbbdddabba'))   ['abbbbbbbbbbb', 'abb', 'a']   預設貪婪匹配,且只增加前面一個字元。

print(re.findall('ab*?','abbbddda'))             ['a', 'a']     數量詞加 ? 改變貪婪匹配


print(re.findall('(ab)*','abababbbddda'))   結果:['ab', '', '', '', '', '', '', ''],注意其實匹配結果是 ababab,
因為findall只打印 分組的內容。其次由於是 * (0 - 無窮),因此空集也會列印。

for i in re.finditer('(ab)*','abababbbddda'):    # 遍歷檢視內容。
    print(i.group())

五、邊界匹配:

              

六、邏輯:

                   邏輯或可以多個使用:      abc | mjk | iop

        

七、re模組正則表示式的函式:

(1)findall用法:

        

                    1、 findall  結果是一個 list,finditer結果是一個迭代物件,可以通過for i in 迭代器 print(i.group()) 遍歷。

                    2、沒有時返回  空列表,可以用於條件語句當中。

                    3、pattern可以呼叫其他函式。

             

                                

(2)raw方法:

import re 
print(re.findall('\\n','abc\nmk'))   # 轉義
print(re.findall('\\\\n','abc\\nmk'))
print(re.findall(r'\\n',r'abc\nmk'))        r 的用法

['\n']    # 換行符
['\\n']     # 普通字元 \n
['\\n']     # 普通字元 \n

(2)match()與search()用法:

                    兩個都只匹配一次,findall匹配多次。

                    兩個函式在有匹配成功時會返回一個匹配物件,通過  該物件.group()檢視:

import re
str1 = '123abcfdd1234'
print(re.match('[a-z]{5}',str1))
print(re.match('\d+',str1))              <_sre.SRE_Match object; span=(0, 3), match='123'>  可放在if 語句中。
print(re.match('\d+',str1).group())        123

                    兩個函式在匹配失敗時會返回None,因此兩個函式常用 if 條件語句當中。

import re
str1 = '123abcf1234'
print(re.match('1234',str1))               # None
print()
if re.match('1234',str1):
    pass
else:
    print('字串不是以1234開頭')
if re.search('1234',str1):
    print('字串包含1234')

答案:
None

字串不是以1234開頭
字串包含1234

# 例子:
2. 判斷以下字元是否全是中文(中文正則模式[\u4E00-\u9FA5])
str='廣東省廣州市';

import re
str1 = '1回家了嗎,'
str2 = '吃飯了嗎hhh'
if re.search('[^\u4E00-\u9FA5]+',str2):   # 注意search與match的區別
    print('不是全是中文')
else:
    print('全是中文!')

(3)re模組中split、finditer、sub、subn用法:

                   finditer 有分組時  預設可以遍歷(for 迴圈 加上 .group( )) 所有匹配字元,包括分組。

                      spilt  不包含分割符  ,
import re
pattern1 = re.compile('\d[a-z]\d')
print(re.split(pattern1,'1a2hjfajh5g678787d833333333'))
print(re.split(pattern1,'1a2hjfajh5g678787d833333333',2))         分割兩次

['', 'hjfajh', '7878', '33333333']
['', 'hjfajh', '78787d833333333']    
             sub 、subn(比sub多了計數)  類似於 str.replace()  的用法,把 。。 替換為 。。。,它支援分組引用。

八:分組 () 與組的引用:

              分組print不僅僅只有findall,search與match同樣具有

1、利用分組編號列印組資訊:

               分組編號預設是從 1 開始的。

 (1) match 與search findall 列印 分組。

import re
str1 = '123456789abcfdd1234'
aaa = re.match('(\d+)(\d+)',str1)      # 第一個是貪婪匹配
print(aaa.group())
print(aaa.group(0))
print(aaa.group(1))                   # 第一組
print(aaa.group(2))                   # 第二組
print(re.findall('(\d+)(\d+)',str1) 

123456789       
123456789
12345678
9
[('12345678', '9'), ('123', '4')]

 2、finditer 列印分組:

                                         預設列印所有匹配資訊

              

3、sub、subn分組引用:

                         

               

                    應用:電話號碼13811119999變成138****9999

十、 利用分組巧妙連結地址:

1、