1. 程式人生 > >Python 正則表達式 (python網絡爬蟲)

Python 正則表達式 (python網絡爬蟲)

寫上 win works 網絡爬蟲 特殊 ner 寫博客 import 計算機程序

  昨天 2018 年 01 月 31 日,農歷臘月十五日。20:00 左右,152 年一遇的月全食、血月、藍月將今晚呈現空中,雖然沒有看到藍月亮,血月、月全食也是勉強可以了,還是可以想像一下一瓶藍月亮洗衣液懸於空上,耳邊是"大家好,我是渣渣灰,給大家推薦一款好玩的遊戲--貪玩藍月......" 22:00左右的樣子,月亮已經出來了,坐下來寫寫博客啦。

  對計算機程序員而言,要問當下前沿什麽方向最流行?我想在大數據、雲計算、人工智能這些方向中,目前位於翹楚的就是大AL(人工智能了),一種產品的流行總是會帶動其依賴品的流行。說的就是 Python 語言,近幾年的勢頭Python越Java座於編程語言首位。Python流行不僅是因為人工智能機器學習的支持,其自身也是有原因的,Python語言學習起來很容易、易懂,這不小學課堂都開Python課了麽。Python又被稱為"膠水語言",與其它的語言的兼容性很好。這也讓不少程序員轉向了Python,更何況當前的人工智能時代即將來臨。

  我最近也在學習Python,說到學習Python極大可能會接觸到 爬蟲 。關於爬蟲,通俗說就是抓取網上數據的機器。涉及到爬蟲,就與本文的點 正則表達式 就是分不開了。

  正則表達式:又稱為規則表達式,百度百科解釋其為通常被用來檢索、替換那些符合某個模式(規則)的文本。這就有點像那些暴力破解密碼的軟件,通過字典一個個組合進行破解。這也是挺考驗計算機運算能力的.

  關於Python正則表達式的知識,我也是從視頻中學習來的。不知道全面否,大家可以進行評論補充。

  正則表達式有以下特殊字符:
  1) ^ . $ * ? + {2} {2, } {2, 5}
  2) [] [^] [a-z] | ()
  3) \s \S \w \W
  4) [\u4E00-\u9FA5] \d

  我將對每個符號進行講解,並舉以實例。

  打開 Eclipse+Pydev、Pycharm 等可以寫Python的IDE(集成開發環境),本人就以 Eclipse+Pydev 為例。

(關於 Pydev 的配置使用可以百度下,關於這個我將在以後會寫一篇博文進行補充。) 在編寫Python過程避免不少要使用漢字,而在 Eclipse+Pydev 初始狀態下要通過Python在屏幕上打印中文是會出現亂碼,對此需要:

  在 Eclipse 的 Windows > Preference > Workspace > Text file encoding 修改 Default (GBK)為 Other UTF-8

  鼠標激活編輯框 按下 Alt + Enter 組合鍵,在出現的窗口 Resource > Text file encoding 修改 Default 為 Other UTF-8

  在 Eslipse 的 Windows > Preference > General > Content Types 中展開列表中的 Text 選擇 Python File ,在下方框 Default encoding 填寫上 UTF-8 再點擊方框後 Update 應用。同時你可以對 Java Source Flie 也設置 UTF-8 ,如果你需要的話。

  更多詳細請轉 https://www.cnblogs.com/jackge/archive/2013/05/19/3086944.html

  首先在編輯框中寫入

#coding:utf-8
import re

  聲明一下編碼 UTF-8 導入正則表達式模塊

  1). ^ 表示必須以特定的字符開頭 如 ^e 則是表示待匹配字符串必須以 e 字符開頭

    $ 表示必須以特定的字符結尾 與 ^ 恰恰相反字符放置也是相反 如 $e 則是表示待匹配字符串必須以 e 字符結尾

    . 表示任意字符 匹配任意字符 表示在待匹配字符串指定位置可以出現任意字符

    * 表示指定字符可以出現任意次 (n >= 0) 如 e* 表達在待匹配字符串中指定位置可以出現任意次數

   就 ^ $ . * 舉個粟子吧(match 函數從首字母開始開始匹配,regex_str如果包含line子串,則匹配成功,返回Match對象,失敗則返回None,若要完全匹配,line要以$結尾)

#coding:utf-8
import re
#導入正則表達式模塊
line = "Hello World"
#待匹配字符串
regex_str = "(^H.*d$)"
if re.match(regex_str, line):
# match 函數  (傳入的參數,要匹配的字符串) 
# 從首字母開始開始匹配,regex_str如果包含line子串,則匹配成功,
# 返回Match對象,失敗則返回None,若要完全匹配,line要以$結尾。
print True else: print False

  運行結果 True 說明匹配成功,^H 以 H 字符開頭 、 .* 任意字符出現任意次、d$以 d 字符結尾,以上都滿足故 True .

  ? 非貪婪匹配,在正則表達式中匹配是貪婪的,程序會盡可能匹配更多的字符,當然這有時候非我們所願.為了防止其貪婪匹配,於是 ? 就派上用場了。(group()用來提出分組截獲的字符串,()用來分組)

#coding:utf-8
import re
#導入正則表達式模塊
line = "heedeeehhlhloooooooo world"
regex_str = ".*(h.*h).*"
match_obj = re.match(regex_str, line)  
if match_obj:
    print (match_obj.group(1))
#group()用來提出分組截獲的字符串,()用來分組
#結果中本來 ‘heedeeeh‘ ‘hh‘ ‘hhlh‘ 都是滿足條件的 #但由於貪婪匹配,盡可能匹配更多的的後面的字符,
#這就匹配到最後一個滿足條件的
‘hlh‘

  運行結果為: hlh ,那麽問題來了 heedeeeh hh hhlh hlh 這樣也滿足條件同時也先出現,那為什麽提取的是 hlh 呢? 原來程序是貪婪匹配的的,程序想盡多可能匹配後面更多的然後就像猴子撿了芝麻丟了西瓜,最後就提取出最後一個符合條件的 hlh ,我們也可以這樣理解貪婪匹配就是反向(從右往左)進行匹配,匹配到的第一項就是貪婪的結果了。

  防止貪婪你可以在之前加上 ? 這樣滿足麽?來看看

#coding:utf-8
import re
#導入正則表達式模塊
line = "heedeeehhlhloooooooo world"
regex_str = ".*?(h.*h).*"
match_obj = re.match(regex_str, line)  
if match_obj:
    print (match_obj.group(1))

  運行結果為 heedeeehhlh 好像不是所料到的結果吧,我只是提取個 heedeeeh 。為麽呢,原來到上述一樣你正向是非貪婪匹配了,而反向卻沒有,所以呢只需在後面也加上百貪婪匹配就行了(註意加在後面字符前邊 即下代碼中 h 前)。運行結果 heedeeeh 就對了。

#coding:utf-8
import re
#導入正則表達式模塊
line = "heedeeehhlhloooooooo world"
regex_str = ".*?(h.*?h).*"
#註意 加在 h 之前
match_obj = re.match(regex_str, line)  
if match_obj:
    print (match_obj.group(1))

  + 表示指定字符至少出現一次及一次以上, h+ 就表示在待匹配字符串指定位置出現 h 至少一次以上

  {2} 表示指定字符出現2次, h{2} 就表示在待匹配字符串中指定位置出現 h 兩次

  {2,} 表示指定字符至少出現2次及以上,(註意 , 後面不能留有空格) 數字不固定 如 h{3,} 表示待匹配字符串中指定位置出現3次以上

  {2,6} 表示指定字符出現 2次-6次 之間, 如 h{3,5} 表示在字符串中指定位置出現次數在 3次-5次 之間

  見代碼 運行結果 heeh 其它就不演示了,差不多的

#coding:utf-8
import re
line = "heehhlhloooooooo world"
regex_str = ".*(he{2,}h).*"
match_obj = re.match(regex_str, line)  
if match_obj:
    print (match_obj.group(1))

  2). [adbc] 表示在待匹配字符串中指定位置指定字符是 adbc 中任一個就滿足條件

    同時可以寫成區間形式 如 [a-z] [0-9] 也可以區間疊加 如 [a-zA-z0-9]

    [^h] 則表示待匹配字符串中指定位置指定字符非 h 就滿足條件

    註意: [.] [*] 此[]中的 . * 就不再表示任意字符和出現任意次數 這個就表示它們本身

    看看粟子吧 運行結果為 hloooo0

#coding:utf-8
import re
line = "heehhlhloooo0 world"
regex_str = ".*(h[^e][a-z].*[0-9]).*"
match_obj = re.match(regex_str, line)  
if match_obj:
    print (match_obj.group(1))

    | 就是或的關系,(h|r)表示待匹配字符串中指定位置只要出現 h 和 r 中的任一個就符合條件

    () 在之前提到過,用來分組,在本實例中與之搭配用的group()就是用來提出分組截獲的字符串 group(1) 就表示截獲第1個分組的字符串 當然要有分組即需有 ()

  實例

#coding:utf-8
import re
line = "hello365"
regex_str = "((hello|hell0o)365)"
match_obj = re.match(regex_str, line)  
if match_obj:
    print (match_obj.group(1))
    print (match_obj.group(2))

  運行分別輸入結果 hello365 hello group(2)就截獲第2個分組中的字符串 即 hello 或 hell0o 中一個

  3). \s 表示待匹配字符串中指定位置指定字符為空格, 而 \S 則是表示非空格 同樣的對單獨使用只對指定的單個字符有效 若要多個則需加上 +

    \w 表示待匹配字符串中指定位置指定字符為 a-z A-Z _ 等同於 [a-zA-Z0-9_], \W 則是除去這些字符的其它字符 像 ~ ! @ # $ % ^ & *

    用實例說話

#coding:utf-8
import re
line = "hello world~"
regex_str = "(\wello\sworld\W)"
match_obj = re.match(regex_str, line)  
if match_obj:
    print (match_obj.group(1))

  運行結果 hello world~ 對吧 沒毛病

  4). \d 表示待匹配字符串中指定位置為數字 [\u4E00-\u9FA5] 則是表示為中文

#coding:utf-8
import re
line = "hello world365嗨"
regex_str = "(hello\sworld\d+[\u4e00-\u9fa5]+)"
match_obj = re.match(regex_str, line)  
if match_obj:
    print (match_obj.group(1))

  運行結果為 hello world365 可以看出 \d 是匹配也出來 [\u4e00-\u9fa5] 也是匹配了出來 不然就不會打印出結果 只是打印結果中不顯示中文 我也表示納悶呢 是更改了編碼的原因麽?

  好,以上就是我學習Python 網絡爬蟲中重要的一節正則表達式,可能不是很全面,甚至還有點小問題,更多的可以去菜鳥教程等各大知名資料網查詢。本人所寫僅供參考。

  對了,關於那個打印結果中為啥中文不顯示,期望有人指點一二. /小糾結

Python 正則表達式 (python網絡爬蟲)