日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

1_正则表达式(python)

發(fā)布時(shí)間:2024/3/26 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 1_正则表达式(python) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 介紹
    • 例子
      • 其他簡(jiǎn)單例子
  • 常用操作符(`.`,`*`,`{}`,`?`,`+`,`^`...)
      • 常用匹配字符串
        • 匹配某個(gè)字符串
        • `.` 點(diǎn) , 匹配符任意的字符
        • 任意的數(shù)字 `\d`
        • `\s` 匹配空白的字符
        • 任意的非數(shù)字 `\D`
        • `\w` 匹配的是 a-z 和A-z 以及數(shù)字0-9和下劃線
        • `\W` 匹配 大小寫(xiě)字母 數(shù)字 和 下劃線 以外的字符
        • `*`匹配多個(gè)字符
        • `?` 問(wèn)號(hào) 匹配一個(gè)或者0個(gè)字符
        • `{m}`匹配m個(gè)字符
        • `{m,n}` 匹配 m到n個(gè)字符
        • `{m,} {,n}` 實(shí)現(xiàn) 長(zhǎng)度的大于等于, 小于等于
        • 脫字號(hào) `^` 以 ...開(kāi)始,
        • `'$' ` 以...結(jié)尾
        • `'|' ` 匹配多個(gè)字符串或者表達(dá)式
        • `[ ]` 組合的方式
          • `| ` 和`[ ]` 兩者之間的差異
        • `+` 號(hào) 的使用
        • 轉(zhuǎn)義字符的使用
  • 常用方法
    • `re.search`
    • `re.match`
    • `re.findall`
    • `re.split`
    • `re.finditer`
    • `re.sub`
      • `subn`
    • `re.compile`
    • re.escape(pattern) 處理轉(zhuǎn)義字符
    • 常用方法(函數(shù))`sub` 案例
  • `re`匹配到的對(duì)象
    • 返回對(duì)象的常用屬性
    • 返回對(duì)象的常用方法
  • 貪婪模式和非貪婪模式
    • 如何非貪婪模式?
  • 關(guān)于分組
    • `()`分組 `\num` 別名
    • `(...)\number`
  • 常用的 `flags`
    • re.A
    • re.DEBUG
    • re.I
    • re.M
    • re.S
    • re.X
    • 指定多個(gè) `flags` 的方式
  • 一些不常見(jiàn)的匹配符號(hào)
    • `(?P=name)`
    • `(?#...)`
  • 正則 斷言匹配
    • `(?=...)` => 匹配 某字符跟隨某某字符 ,匹配前者。
    • `(?!...)`=> 匹配 某字符串 后面沒(méi)跟著某某字符。匹配前者。
    • `(?<=...)` => 匹配前面是某某字符的某字符。匹配后者
    • `(?<!...)`=> 匹配 前面不是某某字符我就匹配某字符。 匹配后者
    • `(?(id/name)yes-pattern|no-pattern)`
  • 常用正則速查


介紹

python re 模塊-正則- python 官方文檔 中文

正則語(yǔ)法 python


書(shū)籍推薦


Jeffrey E. F. Friedl的《Mastering Regular Expressions》一書(shū),
Michael Fitzgerald的《Introducing Regular Expressions》,
Jan Goyvaerts和Steven Levithan寫(xiě)的《Regular Expressions Cookbook》

都是O'Reilly出版社出版,這些書(shū)都非常受歡迎。


regex101 網(wǎng)站

regex101對(duì)于新手是特別有用的網(wǎng)站,可以自動(dòng)生成正則表達(dá)式的解讀。


正則表達(dá)式測(cè)試網(wǎng)站


正則可視化測(cè)試網(wǎng)站


正則表達(dá)式用于搜索、 替換和解析 字符串。 正則表達(dá)式遵循一定的語(yǔ)法規(guī)則, 使用非常靈活, 功能強(qiáng)大。 使用正則表達(dá)式編寫(xiě)一些邏輯驗(yàn)證非常方便, 例如電子郵件地址格式的驗(yàn)證。

正則表達(dá)式是對(duì)字符串(包括普通字符(例如, a 到 z 之間的字母) 和特殊字符) 操作
的一種邏輯公式, 就是用事先定義好的一些特定字符、 及這些特定字符的組合, 組成一個(gè)“規(guī) 則字符串” , 這個(gè)“規(guī)則字符串” 用來(lái)表達(dá)對(duì)字符串的一種過(guò)濾邏輯, 正則表達(dá)式是一種文 本模式, 模式描述在搜索文本時(shí)要匹配一個(gè)或多個(gè)字符串。


一開(kāi)始的例子 如果看不懂 可以先 跳過(guò)。
然后看 search 和 match 方法 。 接著 回過(guò)頭來(lái) 看 常用匹配字符串

然后順序往下看。

當(dāng)然也可以根據(jù)自己的想法 ,隨意觀看。


例子


In [16]: import reIn [17]: pat=r'P(Y|YT|YTH|YTHO)?N'In [18]: p=re.compile(pat) # 面向?qū)ο? 編譯 。 多次使用的正則In [19]: p.findall("i love PN PYN PYTN PYTHN PYTHON PDADN") Out[19]: ['', 'Y', 'YT', 'YTH', 'YTHO']In [21]: p.search("i love PN PYN PYTN PYTHN PYTHON PDADN") Out[21]: <_sre.SRE_Match object; span=(7, 9), match='PN'># 當(dāng)然你也可以使用這種方式 單次 使用。 In [22]: re.findall(pat,"i love PN PYN PYTN PYTHN PYTHON PDADN") Out[22]: ['', 'Y', 'YT', 'YTH', 'YTHO'] # ---------------------------In [23]: pat=r'PYTHON+'In [24]: p=re.compile(pat) In [25]: p.findall("PYTHONN PYTHONNNN PYTHONN PYTHON PYTHO") Out[25]: ['PYTHONN', 'PYTHONNNN', 'PYTHONN', 'PYTHON']# -------------------------------In [27]: pat=r'PY[TH]ON'In [28]: p=re.compile(pat)In [29]: p.findall("PYTON PYHON PYTHON") Out[29]: ['PYTON', 'PYHON']# ------------------------------ # [^5] 將匹配除 '5' 以外的字符 # 那這里就是 匹配除了 TH以外的字符 中括號(hào)這個(gè)位置 # ? 表示0 次或者 1次 In [30]: pat=r'PY[^TH]?ON'In [31]: p=re.compile(pat)In [34]: p.findall("PYON PYaON PYTHON PYcON PYTON PYAON") Out[34]: ['PYON', 'PYaON', 'PYcON', 'PYAON']# ------------------- In [35]: pat='PY{0,3}N' # 圖片中的寫(xiě)法 {:3} 這種寫(xiě)法 不生效 無(wú)法匹配In [36]: p=re.compile(pat)In [37]: p.findall("PYNPYNPYNPYN PYYN PYYYN PYYYYYN") Out[38]: ['PYN', 'PYN', 'PYN', 'PYN', 'PYYN', 'PYYYN']

In [37]: pat=r'^[A-Za-z]+$' # 既然 + 是 1 次或者無(wú)限次 # 那么 我們也可以改為 ? 0次 或者 1次 那就只匹配 1個(gè) 字母了 # 字母 In [38]: p=re.compile(pat)In [39]: p.match("adsfadfasd") Out[39]: <_sre.SRE_Match object; span=(0, 10), match='adsfadfasd'>In [40]: p.match("adsfadfasdADSFAKSD...")In [41]: p.match("adsfadfasdADSFAKSD") Out[41]: <_sre.SRE_Match object; span=(0, 18), match='adsfadfasdADSFAKSD'># ------------------------------ # 字母和數(shù)字 In [43]: pat=r'^[A-Za-z0-9]+$'In [44]: p=re.compile(pat) In [46]: p.search("dasfasdfsdf23141") Out[46]: <_sre.SRE_Match object; span=(0, 16), match='dasfasdfsdf23141'># -------------------------------- # 整數(shù) In [49]: pat=r'^-?\d+$'In [50]: p=re.compile(pat)In [51]: p.search("123") Out[51]: <_sre.SRE_Match object; span=(0, 3), match='123'>In [52]: p.search("+123")In [53]: p.search("-123") Out[53]: <_sre.SRE_Match object; span=(0, 4), match='-123'>In [54]: p.search("-123.2")# ------------------ # 正整數(shù) In [56]: pat=r'^[0-9]*[1-9][0-9]*'In [57]: p=re.compile(pat)In [58]: p.search("31434") Out[58]: <_sre.SRE_Match object; span=(0, 5), match='31434'>In [59]: p.search("031434") Out[59]: <_sre.SRE_Match object; span=(0, 6), match='031434'>In [60]: p.search("0031434") Out[60]: <_sre.SRE_Match object; span=(0, 7), match='0031434'>In [61]: p.search("-31434")# -------------------------- # 郵編 In [62]: pat=r'[1-9]\d{5}'In [63]: p=re.compile(pat)In [64]: p.search("314200") Out[64]: <_sre.SRE_Match object; span=(0, 6), match='314200'>In [65]: p.search("31420000") Out[65]: <_sre.SRE_Match object; span=(0, 6), match='314200'>In [66]: p.search("00031420000") Out[66]: <_sre.SRE_Match object; span=(3, 9), match='314200'># ------------------------ In [68]: pat=r'[\u4e00-\u9fa5]' # 中文字符In [69]: p=re.compile(pat)In [70]: p.search("把酒問(wèn)青天") Out[70]: <_sre.SRE_Match object; span=(0, 1), match='把'>In [71]: p.findall("把酒問(wèn)青天") Out[71]: ['把', '酒', '問(wèn)', '青', '天'] # ------------------------------------ # 國(guó)內(nèi)電話號(hào)碼 In [75]: pat=r'\d{3}-\d{8}|\d{4}-\d{7}'In [76]: p=re.compile(pat)In [77]: p.search("021-6891336")In [78]: p.search("021-68913536") Out[78]: <_sre.SRE_Match object; span=(0, 12), match='021-68913536'># ------------------------------------- # 匹配手機(jī)號(hào)碼 import re # pattern='\d\d\d\d\d\d\d\d\d\d\d' pattern='1[35789]\d\d\d\d\d\d\d\d\d' pattern='1[35789]\d{9}' # 和上面的式子 是不是等價(jià)呢? 是的。 s='13456788765' o=re.match(pattern,s) print(o)#電話號(hào)碼 區(qū)號(hào)-座機(jī)號(hào) 010-3762266 0342-8776262In [12]: import reIn [13]: pattern='1[35789]\d{9}'In [14]: s='13456788765'...: o=re.match(pattern,s)In [15]: o Out[15]: <_sre.SRE_Match object; span=(0, 11), match='13456788765'>

In [2]: import reIn [3]: pat='\d+.\d+.\d+.\d+'In [4]: p=re.compile(pat) # 很明顯 # ip 地址 沒(méi)有 大于 255 的 # 且長(zhǎng)度 是 1 到 3 In [5]: p.findall("255.255.255.255 3333.333.333.333") Out[5]: ['255.255.255.255 ', '3333.333.333.333']In [14]: pat='\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}'In [15]: p=re.compile(pat) # 這個(gè)很明顯 也是有點(diǎn)問(wèn)題的 In [16]: p.findall("255.255.255.255 3333.333.333.333") Out[16]: ['255.255.255.255', '3333.333.333']


In [29]: pat=r'(([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]).){3}([1-9]?\d|1\d{...: 2}|2[0-4]\d|25[0-5])' In [30]: p=re.compile(pat)In [34]: p.fullmatch("255.255.255.255") Out[34]: <_sre.SRE_Match object; span=(0, 15), match='255.255.255.255'> # fullmatch 我個(gè)人感覺(jué) 和 match("^33.33.33.33$") 比較類似。 # 感興趣的可以去 測(cè)試一波 In [36]: p.fullmatch("33.33.33.33") # fullmatch 全匹配 Out[36]: <_sre.SRE_Match object; span=(0, 11), match='33.33.33.33'>

其他簡(jiǎn)單例子

# 1. 驗(yàn)證手機(jī)號(hào)碼 text = "12567347199" ret = re.match('1[34578]\d{9}', text) print(ret.group())# 2. 驗(yàn)證郵箱 text = "pis1@qq.com" ret = re.match('\w+@[a-z0-9]+\.[a-z]+', text) print(ret.group())# 3. 驗(yàn)證 url 協(xié)議 text = "https://www.baidu.com/" ret = re.match('(http|https|ftp)://[^\s]+', text) # 豎線 就是 或的 意思 print(ret.group())# 4. 驗(yàn)證身份證 text = "51152319930228159x" ret = re.match('\d{17}[\dxX]', text) print(ret.group())
import re print('------案例1------') #匹配出一個(gè)字符串首字母為大寫(xiě)字符,后邊都是小寫(xiě)字符,這些小寫(xiě)字母可有可無(wú) pattern='[A-Z][a-z]*' s='Hello' s='HEllo' o=re.match(pattern,s) print(o)print('------案例2------') #匹配出有效的變量名 (字母 、數(shù)字 下劃線 ,而且數(shù)字不能開(kāi)頭) # pattern='[a-zA-Z_][a-zA-Z0-9_]*' pattern='[a-zA-Z_]\w*' s='userName' s='age' s='a' s='_qwe' # s='3er' o=re.match(pattern,s) print(o) print('-------案例3----------') #匹配出1-99直接的數(shù)字 pattern='[1-9]\d?' s='2' s='99' s='100' s='0' o=re.match(pattern,s) print(o) print('----------案例4--------------') #匹配出一個(gè)隨機(jī)密碼8-20位以內(nèi) (大寫(xiě)字母 小寫(xiě)字母 下劃線 數(shù)字) pattern='\w{8,20}' s='123456789' s='abc123qwe_' s='1234567#' o=re.match(pattern,s) print(o)

常用操作符(.,*,{},?,+,^…)


常用匹配字符串

# 重復(fù)數(shù)量符號(hào) ''' * :0次或多次 ? :0次或1次 + :至少1次 {m} :重復(fù)m次 {m,n} :重復(fù)m到n次 {m} :至少重復(fù)m次 {m,} :長(zhǎng)度的大于等于, {,n} :小于等于 '''# 常用的 匹配字符串 ''' . 匹配任意一個(gè)字符(除了\n) [] 匹配列表中的字符 \w 匹配字母、數(shù)字、下劃線,即a-z,A-Z,0-9,_ \W 匹配不是字母、數(shù)字、下劃線 \s 匹配空白字符,即空格(\n,\t) \S 匹配不是空白的字符 \d 匹配數(shù)字,即0-9 \D 匹配非數(shù)字的字符 '''

這里也有一些特殊字符的展示

比如 十六進(jìn)制 Unicode碼 \u0000:\uFFFF
ASCII碼 \x00:\xFF,

  • 中文字符的 Unicode 范圍 \u4e00-\u9fa5

  • ascii 只能匹配 英文的。 范圍為 0- 255 一共 256 個(gè)字符


關(guān)于控制字符 \cA-\cZ 對(duì)應(yīng)的是 ascii 中 1-26 的控制字符 。但是 python不支持 \cA 這種寫(xiě)法

所以不建議 使用 建議使用 十六進(jìn)制碼 或者 \t 這種寫(xiě)法(前提是那個(gè)字符有類似的寫(xiě)法)


演示

看完這個(gè)應(yīng)該就能理解我想說(shuō)的是什么了。

import re str_=""" 中國(guó)牛逼 2020-12-12 2020年12月4日19:47:07 """ pat=r'[\n]' pat1=r'[\x0A]' re.findall(pat,str_) re.findall(pat1,str_)


匹配某個(gè)字符串

# match, 匹配某個(gè)字符串 text = 'hello' ret = re.match('he', text) # match 只會(huì)匹配前面的字符 ahello 就匹配不到了 print(ret.group()) # group 把提匹配到的字符串提取出來(lái)

. 點(diǎn) , 匹配符任意的字符

# 點(diǎn),匹配符任意的字符 text = 'hello' ret = re.match('.', text) # 但是只能匹配一個(gè)字符,但是 不能匹配換行符\n print(ret.group())

任意字符不包括換行符

真正的任意字符可以寫(xiě)成 多種方式 [\w\W] [\s\S] [\d\D] 或者 使用 flags 標(biāo)志 re.S


任意的數(shù)字 \d

# 任意的數(shù)字 \d (0-9) text = "1" ret = re.match('\d', text) print(ret.group())

\s 匹配空白的字符

# \s 匹配空白的字符(例如:\n \r \t ,空格) text = " a b" ret = re.match('\s', text) print(ret.group())

任意的非數(shù)字 \D

# 任意的非數(shù)字 \D text = "+a" ret = re.match('\D', text) print(ret.group())

\w 匹配的是 a-z 和A-z 以及數(shù)字0-9和下劃線

# \w 匹配的是 a-z 和A-z 以及數(shù)字0-9和下劃線text = "ab" ret = re.match('\w', text) print(ret.group())

\W 匹配 大小寫(xiě)字母 數(shù)字 和 下劃線 以外的字符

# \W 與 \w 相反 匹配的text = "+ab"ret = re.match('\W', text)print(ret.group())

*匹配多個(gè)字符

# 匹配多個(gè)字符# * 星號(hào)可以匹配 0個(gè) 或者任意多個(gè) 字符 text = "abdc" ret = re.match('\d*', text) # 這個(gè) '\d*' 匹配任意多個(gè)數(shù)字 print(ret.group())# + 加號(hào) 匹配一個(gè)或者多個(gè)字符 text = "+abdc" # 這個(gè) '\w+'' 匹配一個(gè)以上 a-z 和A-z 以及數(shù)字0-9和下劃線 組成的 字符串 ret = re.match('\w+', text) # 因?yàn)?是從開(kāi)頭開(kāi)始匹配 ,所以這里會(huì)報(bào)錯(cuò) 因?yàn)殚_(kāi)頭 匹配不到 print(ret.group()) import re print('--------*的使用------------') pattern='\d*' s='123qwe' s='123456qwe' s='qwe' o=re.match(pattern,s) print(o)

? 問(wèn)號(hào) 匹配一個(gè)或者0個(gè)字符

# ? 問(wèn)號(hào) 匹配一個(gè)或者0個(gè)字符 text = "abdc+"ret = re.match('\w?', text) print(ret.group()) print('--------?的使用------------') pattern='\d?' s='123qwe' s='1qwe' s='123456qwe' s='qwe' o=re.match(pattern,s) print(o)

{m}匹配m個(gè)字符

# {m}匹配m個(gè)字符 text = "abdc+" ret = re.match('\w{2}', text) # 匹配兩個(gè)字符 print(ret.group()) print('---------{m}-----------') pattern='\d{2}' pattern='\d{3}' pattern='\d{4}' s='123qwe' o=re.match(pattern,s) print(o)

{m,n} 匹配 m到n個(gè)字符

# {m,n}匹配m到n個(gè)字符 text = "abdcdanmd;a" ret = re.match('\w{1,5}', text) print(ret.group()) print('---------{m,n}-----------') pattern='\d{2,5}' s='123qwe' s='123456qwe' s='qwe' o=re.match(pattern,s) print(o)

{m,} {,n} 實(shí)現(xiàn) 長(zhǎng)度的大于等于, 小于等于

print('---------{m,}-----------') pattern='\d{2,}' s='123qwe' s='123456qwe' s='qwe' o=re.match(pattern,s) print(o) # 表示 空字符串。長(zhǎng)度為 0 的字符串。 s = '' o1 = re.match(r'^$', s) print(o1) # 有匹配結(jié)果,匹配到空字符串 s = '1' print(o1) # 無(wú)匹配結(jié)果,返回 None
  • 指定開(kāi)放區(qū)間,省略第2個(gè)值,保留逗號(hào)。例如 a{4, } 匹配4個(gè)或更多個(gè)連續(xù)的字符a。

脫字號(hào) ^ 以 …開(kāi)始,

# 脫字號(hào) '^' 以 ...開(kāi)始, # 放在中括號(hào)[]里面 是取反的意思 text = "hello.py" ret = re.search('^h\w*\.py$', text) # match 是從開(kāi)始去匹配 和 脫字號(hào) 是一樣的功能 print(ret.group())

'$' 以…結(jié)尾

# '$' 以...結(jié)尾 text = "pis1@163.com" ret = re.match('\w+@163.com$', text) # match 是從開(kāi)始去匹配 和 脫字號(hào) 是一樣的功能 print(ret.group())

'|' 匹配多個(gè)字符串或者表達(dá)式

# `'|' ` 匹配多個(gè)字符串或者表達(dá)式 或者的 意思 要么 的意思 text = "http" ret = re.match('(http|https|ftp)$', text) # match 是從開(kāi)始去匹配 和 脫字號(hào) 是一樣的功能 print(ret.group()) # 匹配多個(gè)字符串 import re pattern='aa|bb|cc' s='aa' o=re.match(pattern,s) print(o)s='bb' o=re.match(pattern,s) print(o)s='my name is cc' o=re.search(pattern,s) o=re.match(pattern,s) print(o) print('匹配0-100之間所有的數(shù)字') #匹配0-100之間所有的數(shù)字 0-99|100 pattern=r'[1-9]?\d$|100$' s='1' s='11' s='99' s='100' s='1000' o=re.match(pattern,s) print(o)

關(guān)于 ! 和 ^ 以及 $ 搭配使用

(^|\\s) 就代表 可以是 以 '' 就是沒(méi)有字符開(kāi)始 或者 \s 空白字符開(kāi)始 的 字符
同理 $ 這就是 以沒(méi)有"" 結(jié)尾 或者 空字符結(jié)尾

# import re In [51]: reg Out[51]: '(^|\\s){}(\\s|$)'In [52]: reg2 Out[52]: '(^|\\s){}'In [57]: re.search(reg2.format('classname'),'c classname b'...: ) Out[57]: <re.Match object; span=(1, 11), match=' classname'>In [58]: re.search(reg2.format('classname'),'classname c b'...: ) Out[58]: <re.Match object; span=(0, 9), match='classname'>In [59]: re.search(reg2.format('classname'),'a b classname'...: ) Out[59]: <re.Match object; span=(3, 13), match=' classname'>In [60]: reg2 Out[60]: '(^|\\s){}'In [62]: reg Out[62]: '(^|\\s){}(\\s|$)'In [63]: re.search(reg.format('classname'),'a b classname')...: Out[63]: <re.Match object; span=(3, 13), match=' classname'>In [64]: re.search(reg.format('classname'),'classname c b')...: Out[64]: <re.Match object; span=(0, 10), match='classname '>In [65]: re.search(reg.format('classname'),'c classname b')...: Out[65]: <re.Match object; span=(1, 12), match=' classname '>

[ ] 組合的方式

# [ ] 組合的方式 ,只要,滿足中括號(hào) 中的字符,就可以匹配 text = "a" ret = re.match('[a1]', text) # 匹配 a和 1 print(ret.group()) 8.1 text = "0731-88888888"# 特殊字符 需要 -前面轉(zhuǎn)義 加一個(gè)\ \d是數(shù)字匹配 寫(xiě)一個(gè) + 加號(hào) 就是匹配到 多個(gè)字符 ret = re.match('[\d\-]+', text) print(ret.group())# 8.2 中括號(hào) 代替 \d 以及 反斜杠 \w text = "1213" ret = re.match('[^0-9]+', text) # 這個(gè) ^0-9 是 匹配非0-9的字符 前面加了一個(gè)脫字號(hào) print(ret.group())# 8.2 中括號(hào) 代替 以及 反斜杠 \w text = "1213" ret = re.match('[a-zA-Z0-9_]', text) # 這個(gè) ^0-9 是 匹配非0-9的字符 print(ret.group()) # 8.2 中括號(hào) 代替 以及 反斜杠 \W text = "*" ret = re.match('[^a-zA-Z0-9_]', text) # 這個(gè) ^0-9 是 匹配非0-9的字符 print(ret.group())
| 和[ ] 兩者之間的差異
# 擇一匹配符 和 列表使用差異 import re # pattern=r'[xyz]' # s='y' # o=re.match(pattern,s) # print('使用列表[]:',o) # # pattern=r'x|y|z' # s='y' # o=re.match(pattern,s) # print('擇一匹配符|:',o) # print('字符集([])和擇一匹配符(|)的用法,及它們的差異') # pattern=r'[ab][cd]' # s='ac' # s='ab' # o=re.match(pattern,s) # print(o) # pattern=r'ab[cd]' # # s='ab' # # s='abc' # s='abd' # o=re.match(pattern,s) # print(o) pattern='ab|cd' # s='abc' # s='abd' # s='cd' s='ad' s='ac' o=re.match(pattern,s) print(o)

+ 號(hào) 的使用

print('--------+的使用------------') pattern='\d+' # s='123qwe' # s='1qwe' # s='123456qwe' s='qwe' o=re.match(pattern,s) print(o)

轉(zhuǎn)義字符的使用

當(dāng)然 我們也可以使用 raw 原生字符 s=r'\t123' 類似這樣的語(yǔ)法 會(huì)經(jīng)常 看到。

# 轉(zhuǎn)義字符的使用 print('d:\\a\\b\\c') print('\nabc') print('\\nabc') print('\t123') print('\\t123')import re s='\\t123' # pattern='\\\\t\d*' pattern=r'\\t\d*' o=re.match(pattern,s) print(o)s='\\\\t123' # pattern='\\\\\\\\t\d*' pattern=r'\\\\t\d*' o=re.match(pattern,s) print(o) # 轉(zhuǎn)義字符 和 原生字符串 text = "apple price is $299" ret = re.search("\$\d+", text) # 提取價(jià)格 \ 轉(zhuǎn)義 \$ 只想 讓他作為 普通字符串 print(ret.group())# 原生字符串 text = "\\n" # python 中的 轉(zhuǎn)義字符 把 換行符 轉(zhuǎn)換成一個(gè) 普通反斜杠 text = r"\n" # 前面加一個(gè)r 就是原生的意思 r 就是 raw 原生的意思 別的 正則里面也可以使用 print(text)# 反斜杠 正則和 python 的 \ 反斜杠 都是 轉(zhuǎn)義 ,所以 想要打印出反斜杠 需要4 個(gè)反斜杠text = '\c' # 這里在python 語(yǔ)言中 '\\n'='\n' # python中\(zhòng)\\\c => \\c # 正則中 \\c= > \c # ret = re.match('\\\\c', text) # 轉(zhuǎn)義 ret = re.match(r'\\c', text) # 原生字符串的方式 print(ret.group())

常用方法

常用查詢,主要功能函數(shù)


re.search


# search 方法的使用 import re pattern='hello' s='hello python' # m=re.search(pattern,s) m=re.match(pattern,s) print(m) print(m.group()) print('-------macth和search的區(qū)別----------') pattern='love' s='I love you' m=re.match(pattern,s) print('使用match進(jìn)行匹配',m) o=re.search(pattern,s) print('使用search進(jìn)行匹配',o) # search 是搜索 mat是從開(kāi)始位置匹配In [26]: pattern='love'...: s='I love you'...: m=re.match(pattern,s)In [27]: mIn [28]: o=re.search(pattern,s)In [29]: o Out[29]: <_sre.SRE_Match object; span=(2, 6), match='love'>

re.match

# match 方法的使用 import re s='hello python' pattern='hello' o=re.match(pattern,s) # ----------------- print(o) print(dir(o)) print(o.group()) #返回匹配的字符串 print(o.span()) print(o.start()) # --------------------- print('flags參數(shù)的使用') s='hello python' pattern='Hello' o=re.match(pattern,s,flags=re.I) # re.I # re.IGNORECASE 這兩個(gè)是一樣的。 # 都是忽略大小寫(xiě)print(o) print(o.group())# ------------------- In [3]: print(o) <_sre.SRE_Match object; span=(0, 5), match='hello'>In [4]: print(dir(o)) ['__class__', '__copy__', '__deepcopy__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'end', 'endpos', 'expand', 'group', 'groupdict', 'groups', 'lastgroup', 'lastindex', 'pos', 're', 'regs', 'span', 'start', 'string'] # 這里是這個(gè) match 對(duì)象的屬性In [5]: print(o.group()) #返回匹配的字符串 helloIn [6]: print(o.span()) # 匹配到的字符串的 索引范圍 (0, 5)In [7]: print(o.start()) # 匹配到的字符的 開(kāi)始位置 0In [8]: print('flags參數(shù)的使用') flags參數(shù)的使用In [9]: s='hello python'...: pattern='Hello'...: o=re.match(pattern,s,flags=re.I)# re.I # re.IGNORECASE 這兩個(gè)是一樣的。 # 都是忽略大小寫(xiě) In [10]:In [10]: print(o) <_sre.SRE_Match object; span=(0, 5), match='hello'>In [11]: print(o.group()) hello

re.findall

import re print('---------findall-------------') s='first 1 second 2 third 3' pattern=r'\w+' result=re.findall(pattern,s) print(result)

re.split

import re print('----------split-------------') s='first 11 second 22 third 33' pattern=r'\d+' result=re.split(pattern,s) print(result) result=re.split(pattern,s,maxsplit=2) print(result) # split 分割函數(shù) text = "hello&world ni hao" ret = re.split('[^a-zA-Z]', text) # 以非英文字母為分割 符號(hào) print(ret)

re.finditer

import re print('---------finditer-------------') s='first 1 second 2 third 3' pattern=r'\w+' result=re.finditer(pattern,s) print(result) for i in result:print(i.group(),end='\t') print()

re.sub

import re print('--------sub-------------') phone='2004-959-559 # 這是一個(gè)國(guó)外電話號(hào)碼' #將phone中的注釋去掉 pattern=r'#.*$' result=re.sub(pattern,'',phone) print('sub:',result) pattern=r'#\D*' result=re.sub(pattern,'',phone) print('sub:',result)

subn

執(zhí)行與相同的操作sub(),但返回一個(gè)元組 (new_string, number_of_subs_made) .

import re phone='2004-959-559 # 這是一個(gè)國(guó)外電話號(hào)碼' #將phone中的注釋去掉 pattern=r'#.*$' print('---------subn-----------') result=re.subn(pattern,'',phone) print(result) print(result[0]) print(result[1])

re.compile


import re print('---------compile------------') s='first123 line' pattern=r'\w+' regex=re.compile(pattern) o=regex.match(s) print(o) # compile 函數(shù) text = "the number is 20.50" # 兩個(gè)功能# 功能1 正則表達(dá) 編譯起來(lái)存在內(nèi)存中 # r = re.compile('\d+\.?\d*') # 用 compile 編譯 保存到對(duì)象里 # ret = re.search(r, text) # 這里直接傳入對(duì)象 r 就可以了 # print(ret.group()) # 這樣子 效率比較高# 功能2 為正則寫(xiě)注釋 這是一個(gè)好習(xí)慣 一定要寫(xiě)注釋 方便以后 看 以及調(diào)試 r = re.compile(r""" \d+ # 小數(shù)點(diǎn)前面的數(shù) \.? # 小數(shù)點(diǎn)本身 \d* # 小數(shù)點(diǎn)后面的數(shù)字 """, re.VERBOSE) ret = re.search(r, text) print(ret.group())# 查找 所有空行 '^\s(?=\r?$)\n' rr = re.compile(r""" ^\s # 以空白字符開(kāi)頭 (?=\r?$)# 回車(chē) \n # 換行 """, re.VERBOSE)# re.DOTALL 匹配所有的字符

re.escape(pattern) 處理轉(zhuǎn)義字符

re.escape(pattern)
在中轉(zhuǎn)義特殊字符 模式 . 如果要匹配可能包含正則表達(dá)式元字符的任意文本字符串,則此選項(xiàng)非常有用。例如:

>>> print(re.escape('http://www.python.org')) http://www\.python\.org>>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:" >>> print('[%s]+' % re.escape(legal_chars)) [abcdefghijklmnopqrstuvwxyz0123456789!\#\$%\&'\*\+\-\.\^_`\|\~:]+>>> operators = ['+', '-', '*', '/', '**'] >>> print('|'.join(map(re.escape, sorted(operators, reverse=True)))) /|\-|\+|\*\*|\*

常用方法(函數(shù))sub 案例

import re # 實(shí)際的案例 替換 函數(shù) html = ''' <dd class="job_bt"><h3 class="description">職位描述:</h3><div class="job-detail"><p>崗位職責(zé):</p> <p>1、完成對(duì)復(fù)雜網(wǎng)站的數(shù)據(jù)抓取和交互模擬;</p> <p>2、通過(guò)各種渠道或方式對(duì)相關(guān)網(wǎng)站進(jìn)行抓取;</p> <p>3、不斷完善并維護(hù)相關(guān)網(wǎng)站的抓取,使之穩(wěn)定運(yùn)行,核心邏輯必須有單元測(cè)試;</p> <p>4、善于靈活運(yùn)用各種非爬蟲(chóng)技術(shù)解決爬蟲(chóng)相關(guān)問(wèn)題;</p> <p>5、隨時(shí)響應(yīng)并解決突發(fā)問(wèn)題;</p> <p>6、完成領(lǐng)導(dǎo)交辦的其他工作。</p> <p><br></p> <p>任職要求:</p> <p>1、本科以上學(xué)歷,三年以上網(wǎng)站抓取經(jīng)驗(yàn),有電商網(wǎng)站、秒殺相關(guān)抓取經(jīng)驗(yàn);</p> <p>2、有較強(qiáng)的網(wǎng)站分析能力,熟知各種反爬措施及相關(guān)解決辦法</p> <p>技能要求;</p> <p>3、熟練使用eventlet、gevent、requests、selenium等技術(shù)實(shí)現(xiàn)高并發(fā)穩(wěn)定抓取;</p> <p>4、熟練使用消息隊(duì)列(MQ)、celery等異步框架實(shí)現(xiàn)分布式任務(wù)處理;</p> <p>5、熟知HTTP、TCP、Socket等底層知識(shí);</p> <p>6、熟練掌握Fiddler、Http debugger等抓捕工具;</p> <p>7、熟悉MySQL、MongoDB基本使用;</p> <p>8、熟悉Scapy,熟悉Javascript,有一定的分析能力;</p> <p>9、能使用mock進(jìn)行單元測(cè)試;</p> <p>10、善于溝通、有團(tuán)隊(duì)協(xié)作精神。</p> <p><br></p> <p>我們的團(tuán)隊(duì)成員都是80后、90后,我們是充滿激情和干勁的團(tuán)隊(duì),我們是有夢(mèng)想有追求的團(tuán)隊(duì)……</p> <p>如果你有滿腔熱忱,如果你不想碌碌無(wú)為,如果你想通過(guò)自己的努力成為合伙人……</p> <p>來(lái)吧!朋友,加入我們,我們會(huì)給你釋放夢(mèng)想的平臺(tái),我們會(huì)讓你的美夢(mèng)成真……</p> <p>期待有為的你加入!!!</p> <p>&nbsp;</p> <p>為了讓我們的小伙伴能夠快樂(lè)、健康的在一起為了夢(mèng)想而努力,我們提供了以下多種福利及文化活動(dòng):</p> <p>1、每天工作8小時(shí),彈性工作時(shí)間;</p> <p>2、公司年度健康體檢,小伙伴在為公司默默奉獻(xiàn)的同時(shí),公司也時(shí)刻關(guān)注著他們的健康。</p> <p>3、量身定制的培訓(xùn)計(jì)劃,讓員工在我們細(xì)致入微的幫助下更快的融入團(tuán)隊(duì)。</p> <p>4、豐富的企業(yè)文化活動(dòng):</p> <p>?&nbsp; 每天:美味的零食和飲品;</p> <p>?&nbsp; 每?jī)芍?#xff1a;組織大家去打乒乓球、羽毛球,小伙伴的健康是我們一直關(guān)注的;</p> <p>?&nbsp; 每月:家人生日會(huì)(給每位壽星唱著生日快樂(lè)歌,分享美味可口的蛋糕,盡享溫馨時(shí)刻);</p> <p>?&nbsp; 季度:團(tuán)隊(duì)建設(shè)、拓展活動(dòng);</p> <p>?&nbsp; 年度:大型年會(huì)(辛苦了一年的匯游科技家人,一起收獲一起分享)。</p> <p>5、每年1次調(diào)薪,兩次豐厚的績(jī)效獎(jiǎng)金,付出與回報(bào)永遠(yuǎn)成正比哦。</p> <p>6、節(jié)日禮品、生日禮品、結(jié)婚生子禮金等。</p> <p>7、每天午餐補(bǔ)助,每月全勤獎(jiǎng)勵(lì)。</p> <p>…………</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>匯游科技祝您面試成功!</p></div></dd> '''ret = re.sub('<.+?>', '', html) # 非貪婪 模式 ,把 非標(biāo)簽的數(shù)據(jù)替換掉了 print(ret)

re匹配到的對(duì)象

比如match 或者search 匹配到 的對(duì)象 也就是 這些函數(shù)的 返回值

可以這樣理解。

<_sre.SRE_Match object; span=(0, 11), match='33.33.33.33'> 這個(gè)就是一個(gè)返回對(duì)象 。
match對(duì)象
匹配對(duì)象

返回對(duì)象的常用屬性

返回對(duì)象的常用方法


貪婪模式和非貪婪模式

re 默認(rèn)是貪婪模式

如何非貪婪模式?

*?, +?, ?? 這些符號(hào) 就代表非貪婪 模式 (也叫最小匹配操作符)

比如 你使用 (.*?) 匹配任意字符 但是 是非貪婪 模式 。 只匹配最少的數(shù)據(jù)。

# 貪婪模式 與 非貪婪模式 # 貪婪模式就是會(huì) 盡量多的 字符'\d+' # 非貪婪模式'\d+?' 匹配到 +的 最小的 條件 # + 表示(1個(gè)或者多個(gè)匹配) text = "0123456" ret = re.search('\d+?', text) # match 是從開(kāi)始去匹配 和 脫字號(hào) 是一樣的功能 print(ret.group())text = "<h1>標(biāo)題1</h1>" ret = re.search('<.+?>', text) # 非貪婪模式 問(wèn)號(hào) 去掉 就是 貪婪模式 print(ret.group()) # 小案例 匹配0-101之間的數(shù)字 # 可以出現(xiàn)的是 1 2 3 9 100 88 # 不可以出現(xiàn)的是 09 101 # 有三種情況 1位1-9 2位10-99 3位 100 for text in range(1, 102):text1 = str(text)ret = re.search("^[1-9]\d?$|100$", text1)print(ret.group())

關(guān)于分組

(...)
匹配圓括號(hào)內(nèi)的任何正則表達(dá)式,并指示組的開(kāi)始和結(jié)束;組的內(nèi)容可以在執(zhí)行匹配后檢索,稍后在字符串中與 \number 特殊順序,如下所述。匹配文字 '(' 或 ')' 使用 \( 或 \) 或?qū)⑺鼈兝ㄔ谧址愔?#xff1a; [(] , [)] .

\number
匹配同一號(hào)碼組的內(nèi)容。組從1開(kāi)始編號(hào)。例如, (.+) \1 'the the' 或 '55 55' ,但不匹配 'thethe' (注意組后的空格)。

# (ab) 將括號(hào)中的字符作為一個(gè)分組 # \num 引用分組num匹配到的字符串In [99]: re.match(r"(.)\1+","66555") Out[99]: <_sre.SRE_Match object; span=(0, 2), match='66'> # 注意這種形式 無(wú)法 匹配長(zhǎng)度 為 1 的 字符 # 因?yàn)?這是 匹配同一 號(hào)碼組的 內(nèi)容。 # 進(jìn)去之后先被分組了 一個(gè)數(shù)字。 # 然后和他同一號(hào)碼組的 數(shù)字 就沒(méi)有了 # 不信的話。 分組之后 組里面 就只有一個(gè) 數(shù)字。 可以 看看 # --------------------------------In [100]: re.match(r"(.+)\1","thethe")Out[100]: <_sre.SRE_Match object; span=(0, 6), match='thethe'>In [101]: re.match(r"(.+) \1","thethe") # 這個(gè)沒(méi)有輸出# 注意 組括號(hào) 和 \number 之間的空格 In [102]: re.match(r"(.+) \1","the the")Out[102]: <_sre.SRE_Match object; span=(0, 7), match='the the'>


()分組 \num 別名

import re# 示例 1 匹配座機(jī)號(hào)碼 使用 ( ) 括號(hào) 分組 print('匹配座機(jī)號(hào)碼') # 匹配座機(jī)號(hào)碼 區(qū)號(hào){3,4}-電話號(hào)碼{5,8} 010-43222 0432-447727 pattern=r'\d{3,4}-[1-9]\d{4,7}$' pattern=r'(\d{3,4})-([1-9]\d{4,7}$)' s='010-786545' o=re.match(pattern,s) print(o) print(o.group()) print(o.group(1)) print(o.group(2)) # print(o.groups()) # print(o.groups()[0]) # 這樣子 group() 返回的是字符串 所以這種方式 就是類似元組 切片 索引訪問(wèn) 字符串。 # print(o.groups()[1])


print('匹配出網(wǎng)頁(yè)標(biāo)簽內(nèi)的數(shù)據(jù)') # 示例 2 分組示例 \num # pattern=r'<.+><.+>.+</.+></.+>'pattern=r'<(.+)><(.+)>.+</\2></\1>' s='<html><head>head部分</head></html>' # s='<html><title>head部分</head></body>' o=re.match(pattern,s) print(o)


# ( ) \1 # 正確示范,()有分組作用,正則表達(dá)式中\(zhòng)1可以取到分組的第一個(gè) import rehtml_str = "<h1>hahaha</h1>" ret = re.match(r"<(\w*)>.*</\1>", html_str) print(ret.group())


# ( ) \1 # 正確示范,()有分組作用,正則表達(dá)式中 \1 和 \2取值順序 import rehtml_str = "<body><h1>hahaha</h1></body>" ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>", html_str) print(ret.group())


# 示例 3 分組起別名 # (?p<name>) 分別起組名 # (?p=name) 引用別名為name分組匹配到的字符串# 示例html標(biāo)簽 .+ 匹配 起別名 # <(?P<k_html>.+)>#<body><h1><div><div></div></div></h1></body> print('(?P<name>) 分別起組名') pattern=r'<(?P<k_html>.+)><(?P<k_head>.+)>.+</(?P=k_head)></(?P=k_html)>' s='<html><head>head部分</head></html>' # s='<html><title>head部分</head></body>' o=re.match(pattern,s) print(o)

通過(guò)觀察可以發(fā)現(xiàn) 取了別名 就有了 groupdict 了



# -------------------------------(?P<name>) #命名的格式 (注意P是大寫(xiě)的) (?P=name) #取值的格式 # import rehtml_str = "<body><h1>hahaha</h1></body>" ret = re.match(r"<(?P<p1>\w*)><(?P<p2>\w*)>.*</(?P=p2)></(?P=p1)>", html_str) print(ret.group())



import re# 分組 text = "apple's price $99, orange's price $10" ret = re.search('.*(\$\d+).*(\$\d+)', text) # 將整個(gè)字符串提取出來(lái)括號(hào)里是分組的意思print(ret.group()) # 整個(gè)正則表達(dá)式 就是一個(gè) 大的分組,可以寫(xiě)0或者不寫(xiě) 都是可以的 print(ret.group(1)) # 第一個(gè)分組 print(ret.group(2)) # 第二個(gè)分組 print(ret.group(1, 2)) # 兩個(gè)分組 拿出來(lái) print(ret.groups()) # 所有 的子分組 都拿出來(lái)


(...)\number

# (\number)In [101]: a='WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB' In [102]: a Out[102]: 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB'In [103]: re.sub(r"(.)\1+",lambda x:str(len(x.group(0)))+ x.group(1),a)Out[103]: '12WB12W3B24WB'In [109]: re.sub(r"(.)\1+",lambda x:print(x),a) <_sre.SRE_Match object; span=(0, 12), match='WWWWWWWWWWWW'> <_sre.SRE_Match object; span=(13, 25), match='WWWWWWWWWWWW'> <_sre.SRE_Match object; span=(25, 28), match='BBB'> <_sre.SRE_Match object; span=(28, 52), match='WWWWWWWWWWWWWWWWWWWWWWWW'> Out[109]: 'BB'


group 都是 從 1 開(kāi)始編碼

group(0) 等價(jià)于 group() 返回整個(gè) 匹配 。

groups
返回一個(gè)包含匹配的所有子組的元組,從1到模式中的所有組。這個(gè) default 參數(shù)用于沒(méi)有參與匹配的組;它默認(rèn)為 None .

In [263]: m = re.match(r"(\d+)\.(\d+)", "24.1632")In [264]: m.groups() Out[264]: ('24', '1632')


關(guān)于分組的 一些實(shí)際 例子

分組的反向引用 ( 就是那個(gè) \1)

import re import requests pat="<(\w+)>(.+)<\/\1>" # 基本套路 不過(guò)對(duì)于一些復(fù)雜的 html 標(biāo)簽無(wú)法 提取 res=requests.get("http://www.baidu.com") res.encoding='utf-8' html=res.textpat=r"<(head)>(.+)</\1>" # 稍加 修改 re.findall(pat,html) # ---------------------------- # 返回結(jié)果 # [('head', #'<meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css&gt;&lt;title&gt;百度一下,你就知道&lt;/title&gt;')]pat=r"<(div)\s*.*?>(.+)</\1>" # 再次修改 re.findall(pat,html) # 返回結(jié)果 # [('div', # ' <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新聞</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地圖</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>視頻</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>貼吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;amp;tpl=mn&amp;amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登錄</a> </noscript> <script>document.write(\'<a href="http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=\'+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">登錄</a>\');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多產(chǎn)品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com&gt;關(guān)于百度&lt;/a&gt; <a href=http://ir.baidu.com&gt;About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/&gt;使用百度前必讀&lt;/a&gt;&amp;nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意見(jiàn)反饋</a>&nbsp;京ICP證030173號(hào)&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> ')]pat=r"<(\w+)\s*.*?>(.+)</\1>" # pat="<(\w+)>(.+)<\/\1>" 完成我在一開(kāi)始想用這個(gè)操作的事情。 re.findall(pat,html) # 返回結(jié)果 #[('html', # ' <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css&gt;&lt;title&gt;百度一下,你就知道&lt;/title&gt;&lt;/head&gt; <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新聞</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地圖</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>視頻</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>貼吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;amp;tpl=mn&amp;amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登錄</a> </noscript> <script>document.write(\'<a href="http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=\'+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">登錄</a>\');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多產(chǎn)品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com&gt;關(guān)于百度&lt;/a&gt; <a href=http://ir.baidu.com&gt;About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/&gt;使用百度前必讀&lt;/a&gt;&amp;nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意見(jiàn)反饋</a>&nbsp;京ICP證030173號(hào)&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> ')]

一些運(yùn)行效果

常用的 flags

re.A

re.ASCII

制作 \w , \W , \b , \B , \d , \D , \s 和 \S 只執(zhí)行ASCII匹配,而不是完全Unicode匹配。這只對(duì)Unicode 模式有意義,而對(duì)于字節(jié)模式則被忽略。對(duì)應(yīng)于內(nèi)聯(lián)標(biāo)志 (?a) .

請(qǐng)注意,為了向后兼容, re.U 標(biāo)志仍然存在(及其同義詞 re.UNICODE 及其嵌入的對(duì)應(yīng)項(xiàng) (?u) ,但在python 3中這些是多余的,因?yàn)樽址钠ヅ淠J(rèn)為Unicode(字節(jié)不允許使用Unicode匹配)。

re.DEBUG

顯示有關(guān)已編譯表達(dá)式的調(diào)試信息。沒(méi)有對(duì)應(yīng)的內(nèi)聯(lián)標(biāo)志。

re.I

re.IGNORECASE

執(zhí)行不區(qū)分大小寫(xiě)的匹配; 對(duì)應(yīng)于內(nèi)聯(lián)標(biāo)志 (?i) .

re.M

re.MULTILINE

指定時(shí),模式字符 '^' 匹配字符串的開(kāi)頭和每行的開(kāi)頭(緊跟每行換行符);以及模式字符 $ 匹配字符串的結(jié)尾和每行的結(jié)尾(緊接著每行換行符的前面)。默認(rèn)情況下, '^' 僅在字符串的開(kāi)頭匹配,并且 '$' 只在字符串的末尾,在字符串末尾的換行符(如果有)之前。對(duì)應(yīng)于內(nèi)聯(lián)標(biāo)志 (?m) .

其實(shí)一句話 就是 換行符為邊界

比如 22\n3322\n3322\n33 如果我要獲取 以某某開(kāi)頭的兩位數(shù)字字符。 以換行符為邊界。 那就是 22 33 33 33


可以理解為 行首 行尾 的概念。

而不是字符串的首尾。

如果flags 用 re.M 但是想要 獲取字符串首部 那就是 \A 需要寫(xiě)在開(kāi)頭 ,獲取字符串尾部是 \Z 需要寫(xiě)在后面

import re pat=r"(?m)^\d{2}" str_="22\n3322\n3322\n33" re.findall(pat,str_)

關(guān)于 \A \Z

import re pat=r"(?m)^\A\d{2}" str_="22\n3322\n3322\n33" re.findall(pat,str_) pat=r"(?m)^\d{2}\Z" re.findall(pat,str_)

re.S

re.DOTALL

使'.'特殊字符完全匹配任何字符,包括換行符;如果沒(méi)有此標(biāo)志, '.' 會(huì)匹配任何東西 除了 換行符對(duì)應(yīng)于內(nèi)聯(lián)標(biāo)志 (?s) .


re.X

re.VERBOSE

此標(biāo)志允許您編寫(xiě)看起來(lái)更好、更可讀的正則表達(dá)式,方法是允許您直觀地分隔模式的邏輯部分并添加注釋。


指定多個(gè) flags 的方式

re.I | re.M 用 | 表達(dá)符 表示 flags 被設(shè)置為了 re.I 和 re.M

或者使用內(nèi)聯(lián)的方式 (?im) 并且這個(gè) 標(biāo)志要寫(xiě)在 最開(kāi)始的位置。 否則會(huì)報(bào) 警告信息

import re str_=""" One1 oNe2 onE3 noe4 """ pat=r"^one\w+" pat1=r"(?im)one\w+" re.findall(pat,str_) re.findall(pat1,str_) re.findall(pat,str_,flags=re.I|re.M) re.findall(pat,str_,flags=re.I) re.findall(pat,str_,flags=re.M)

一些不常見(jiàn)的匹配符號(hào)

(?P=name)

  • (?P< name >)
    • 命名的格式 (注意P是大寫(xiě)的)
  • (?P=name)
    • 取值的格式

對(duì)命名組的后向引用;它與先前命名組匹配的任何文本匹配 name .

<(?P<p1>\w*)><(?P<p2>\w*)>.*</(?P=p2)></(?P=p1)>

以這為 例子

import rehtml_str = "<body><h1>hahaha</h1></body>" ret = re.match(r"<(?P<p1>\w*)><(?P<p2>\w*)>.*</(?P=p2)></(?P=p1)>", html_str) print(ret.group())

(?#...)

注釋;括號(hào)的內(nèi)容被忽略。

相當(dāng)于沒(méi)寫(xiě)。 就可以理解為 就是 寫(xiě)的注釋


正則 斷言匹配

斷言的組成之一是邊界。對(duì)于文本、詞或模式,邊界可以用來(lái)表明它們的起始或終止部分(如向前斷言,向后斷言以及條件表達(dá)式)。

(?=...) => 匹配 某字符跟隨某某字符 ,匹配前者。

匹配如果 ... 匹配下一個(gè),但不使用任何字符串。這叫A lookahead assertion 前瞻性斷言或者說(shuō) 先行斷言 . 例如, Isaac (?=Asimov) 將匹配 'Isaac ' 只有在后面跟著 'Asimov' .


向前斷言:例如,對(duì)于 Jack(?=Sprat),“Jack”在跟有“Sprat”的情況下才會(huì)得到匹配./Jack(?=Sprat|Frost)/ “Jack”后跟有“Sprat”或“Frost”的情況下才會(huì)得到匹配。不過(guò), 匹配結(jié)果 不包括 “Sprat”或“Frost”

所謂的先行是指的 匹配的東西先行
條件后行。

tips: 記憶小技巧 有箭頭的斷言 條件都寫(xiě)在 前面的。
所以 都是后行。

先行斷言 匹配的模式字符寫(xiě)在 前面
后行斷言 匹配的模式字符串寫(xiě)在后面

斷言就是指定條件。 不匹配字符。


In [81]: pat=r'Isaac (?=Asimov)'In [82]: p=re.compile(pat)In [85]: p.search("Isaac Asimovv") # 可以理解為 匹配 以某字符串結(jié)尾的 字符。 Out[85]: <_sre.SRE_Match object; span=(0, 6), match='Isaac '>


(?!...)=> 匹配 某字符串 后面沒(méi)跟著某某字符。匹配前者。

匹配如果 ... 與下一個(gè)不匹配。這是一個(gè) negative lookahead assertion 否定超前斷言 向前否定斷言. 例如, Isaac (?!Asimov) 將匹配 'Isaac ' 只要后面不是 'Asimov' .

需要注意 ()里 這個(gè)是條件 是不會(huì)被匹配到的

In [69]: pat=r'Isaac (?!Asimov)' In [74]: p.search("Isaac Asimo") Out[74]: <_sre.SRE_Match object; span=(0, 6), match='Isaac '> In [76]: p.search("Isaac Asimov")# 不匹配In [77]: p.search("Isaac Asimovv")# 不匹配In [78]: p.search("Isaac aAsimovv") # 匹配 # 可以理解為 匹配 不以 某字符串 結(jié)尾的 字符 Out[78]: <_sre.SRE_Match object; span=(0, 6), match='Isaac '>


(?<=...) => 匹配前面是某某字符的某字符。匹配后者

如果字符串中的當(dāng)前位置前面有匹配項(xiàng),則匹配 ... 在當(dāng)前位置結(jié)束。這叫A positive lookbehind assertion 肯定斷言 或者叫做 向后肯定斷言 .

(?<=abc)def 將在中找到匹配項(xiàng) 'abcdef' ,因?yàn)閘ookback將備份3個(gè)字符并檢查包含的模式是否匹配。

包含的模式必須只匹配某個(gè)固定長(zhǎng)度的字符串,這意味著 abc 或 a|b 是允許的,但是 a* 和 a{{3,4}} 不是

請(qǐng)注意,以正的lookbehind斷言開(kāi)頭的模式在被搜索的字符串的開(kāi)頭將不匹配;您很可能希望使用 search() 函數(shù)而不是 match() 功能:

需要注意 ()里 這個(gè)是條件 是不會(huì)被匹配到的

import re # 前面 有 abc 那么 我就 匹配 def m = re.search('(?<=abc)def', 'abcdef') # 可以理解為以某字符串開(kāi)頭的 字符 m.group(0)# 輸出 'def'# 此示例查找連字符后的單詞: # 前面有連字符 那么我就匹配后面的 這個(gè)字符 m = re.search(r'(?<=-)\w+', 'spam-egg') m.group(0)'egg'


(?<!...)=> 匹配 前面不是某某字符我就匹配某字符。 匹配后者

如果字符串中的當(dāng)前位置前面沒(méi)有匹配項(xiàng),則匹配 … . 這叫A negative lookbehind assertion 向后否定斷言.

與正查找斷言類似,包含的模式必須只匹配某些固定長(zhǎng)度的字符串。

以負(fù)的lookbehind斷言開(kāi)頭的模式可能在要搜索的字符串的開(kāi)頭匹配。

需要注意 ()里 這個(gè)是條件 是不會(huì)被匹配到的

In [87]:...: import re# 前面 不是 adc 那么我就匹配后面的字符...: m = re.search('(?<!abc)def', 'abcdef') # 未匹配到任何東西 In [90]:...: import re...: m = re.search('(?<!abc)def', 'bcdef') # 可以理解為不以某某開(kāi)頭的字符 后面的字符In [91]: m.group() Out[91]: 'def'

(?(id/name)yes-pattern|no-pattern)

如果給定的組 id 或 name 指向的組 有值 將嘗試 使用 yes-pattern 匹配一些字符 ,否則嘗試使用 no-pattern 匹配一些字符 。 no-pattern 是可選的,可以省略。


特殊序列包括 '\' 以及下面列表中的一個(gè)字符。如果普通字符不是一個(gè)ASCII數(shù)字或一個(gè)ASCII字母,那么得到的RE將與第二個(gè)字符匹配。例如, \$ 與 '$'匹配 .


相信 看完 這幾張圖 然后 自己實(shí)驗(yàn) 一下 所有人都能理解這是什么意思。

  • pat="(\w+@\w+(?:\.\w+)+)"
  • pat="(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|>$)"



  • s1 的分組 id為1 的 匹配了 < 說(shuō)明有值 那么match=<user@host.com 使用 yes 模式 嘗試匹配> 因?yàn)?s1是 user@host.com 所以匹配成功
  • s3的分組id 為1 的 組 值為None 所以使用 no 模式 。然后 s3=user@host.com> 所以no 模式我寫(xiě)的 匹配 > 也匹配到了。


常用正則速查

/這里是正則/

js 中正則就是 寫(xiě)在 // 下劃線中的

示例(比如我要驗(yàn)證用戶名)

import re pat='^[a-z0-9_-]{3,16}$' str="你要驗(yàn)證的字符串" re.match(pat,str)

如果已有的正則 不符合你的 要求

記得自己修改一下哦


用戶名密碼十六進(jìn)制值電子郵箱URLIP 地址HTML 標(biāo)簽刪除代碼\\注釋Unicode編碼中的漢字范圍
/^[a-z0-9_-]{3,16}$/
/^[a-z0-9_-]{6,18}$/
/^#?([a-f0-9]{6}|[a-f0-9]{3})$/
/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/
/^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/
/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/
/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
/^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/
(?<!http:|\S)//.*$
/^[\u2E80-\u9FFF]+$/

總結(jié)

以上是生活随笔為你收集整理的1_正则表达式(python)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。