1_正则表达式(python)
文章目錄
- 介紹
- 例子
- 其他簡單例子
- 常用操作符(`.`,`*`,`{}`,`?`,`+`,`^`...)
- 常用匹配字符串
- 匹配某個字符串
- `.` 點 , 匹配符任意的字符
- 任意的數字 `\d`
- `\s` 匹配空白的字符
- 任意的非數字 `\D`
- `\w` 匹配的是 a-z 和A-z 以及數字0-9和下劃線
- `\W` 匹配 大小寫字母 數字 和 下劃線 以外的字符
- `*`匹配多個字符
- `?` 問號 匹配一個或者0個字符
- `{m}`匹配m個字符
- `{m,n}` 匹配 m到n個字符
- `{m,} {,n}` 實現(xiàn) 長度的大于等于, 小于等于
- 脫字號 `^` 以 ...開始,
- `'$' ` 以...結尾
- `'|' ` 匹配多個字符串或者表達式
- `[ ]` 組合的方式
- `| ` 和`[ ]` 兩者之間的差異
- `+` 號 的使用
- 轉義字符的使用
- 常用方法
- `re.search`
- `re.match`
- `re.findall`
- `re.split`
- `re.finditer`
- `re.sub`
- `subn`
- `re.compile`
- re.escape(pattern) 處理轉義字符
- 常用方法(函數)`sub` 案例
- `re`匹配到的對象
- 返回對象的常用屬性
- 返回對象的常用方法
- 貪婪模式和非貪婪模式
- 如何非貪婪模式?
- 關于分組
- `()`分組 `\num` 別名
- `(...)\number`
- 常用的 `flags`
- re.A
- re.DEBUG
- re.I
- re.M
- re.S
- re.X
- 指定多個 `flags` 的方式
- 一些不常見的匹配符號
- `(?P=name)`
- `(?#...)`
- 正則 斷言匹配
- `(?=...)` => 匹配 某字符跟隨某某字符 ,匹配前者。
- `(?!...)`=> 匹配 某字符串 后面沒跟著某某字符。匹配前者。
- `(?<=...)` => 匹配前面是某某字符的某字符。匹配后者
- `(?<!...)`=> 匹配 前面不是某某字符我就匹配某字符。 匹配后者
- `(?(id/name)yes-pattern|no-pattern)`
- 常用正則速查
介紹
python re 模塊-正則- python 官方文檔 中文
正則語法 python
書籍推薦
Jeffrey E. F. Friedl的《Mastering Regular Expressions》一書,
Michael Fitzgerald的《Introducing Regular Expressions》,
Jan Goyvaerts和Steven Levithan寫的《Regular Expressions Cookbook》
都是O'Reilly出版社出版,這些書都非常受歡迎。
regex101 網站
regex101對于新手是特別有用的網站,可以自動生成正則表達式的解讀。
正則表達式測試網站
正則可視化測試網站
正則表達式用于搜索、 替換和解析 字符串。 正則表達式遵循一定的語法規(guī)則, 使用非常靈活, 功能強大。 使用正則表達式編寫一些邏輯驗證非常方便, 例如電子郵件地址格式的驗證。
正則表達式是對字符串(包括普通字符(例如, a 到 z 之間的字母) 和特殊字符) 操作
的一種邏輯公式, 就是用事先定義好的一些特定字符、 及這些特定字符的組合, 組成一個“規(guī) 則字符串” , 這個“規(guī)則字符串” 用來表達對字符串的一種過濾邏輯, 正則表達式是一種文 本模式, 模式描述在搜索文本時要匹配一個或多個字符串。
一開始的例子 如果看不懂 可以先 跳過。
然后看 search 和 match 方法 。 接著 回過頭來 看 常用匹配字符串
然后順序往下看。
當然也可以根據自己的想法 ,隨意觀看。
例子
In [16]: import reIn [17]: pat=r'P(Y|YT|YTH|YTHO)?N'In [18]: p=re.compile(pat) # 面向對象 編譯 。 多次使用的正則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'># 當然你也可以使用這種方式 單次 使用。 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以外的字符 中括號這個位置 # ? 表示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' # 圖片中的寫法 {:3} 這種寫法 不生效 無法匹配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 次或者無限次 # 那么 我們也可以改為 ? 0次 或者 1次 那就只匹配 1個 字母了 # 字母 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'># ------------------------------ # 字母和數字 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'># -------------------------------- # 整數 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")# ------------------ # 正整數 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("把酒問青天") Out[70]: <_sre.SRE_Match object; span=(0, 1), match='把'>In [71]: p.findall("把酒問青天") Out[71]: ['把', '酒', '問', '青', '天'] # ------------------------------------ # 國內電話號碼 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'># ------------------------------------- # 匹配手機號碼 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}' # 和上面的式子 是不是等價呢? 是的。 s='13456788765' o=re.match(pattern,s) print(o)#電話號碼 區(qū)號-座機號 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 地址 沒有 大于 255 的 # 且長度 是 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) # 這個很明顯 也是有點問題的 In [16]: p.findall("255.255.255.255 3333.333.333.333") Out[16]: ['255.255.255.255', '3333.333.333']
其他簡單例子
# 1. 驗證手機號碼 text = "12567347199" ret = re.match('1[34578]\d{9}', text) print(ret.group())# 2. 驗證郵箱 text = "pis1@qq.com" ret = re.match('\w+@[a-z0-9]+\.[a-z]+', text) print(ret.group())# 3. 驗證 url 協(xié)議 text = "https://www.baidu.com/" ret = re.match('(http|https|ftp)://[^\s]+', text) # 豎線 就是 或的 意思 print(ret.group())# 4. 驗證身份證 text = "51152319930228159x" ret = re.match('\d{17}[\dxX]', text) print(ret.group())import re print('------案例1------') #匹配出一個字符串首字母為大寫字符,后邊都是小寫字符,這些小寫字母可有可無 pattern='[A-Z][a-z]*' s='Hello' s='HEllo' o=re.match(pattern,s) print(o)print('------案例2------') #匹配出有效的變量名 (字母 、數字 下劃線 ,而且數字不能開頭) # 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直接的數字 pattern='[1-9]\d?' s='2' s='99' s='100' s='0' o=re.match(pattern,s) print(o) print('----------案例4--------------') #匹配出一個隨機密碼8-20位以內 (大寫字母 小寫字母 下劃線 數字) pattern='\w{8,20}' s='123456789' s='abc123qwe_' s='1234567#' o=re.match(pattern,s) print(o)
常用操作符(.,*,{},?,+,^…)
常用匹配字符串
# 重復數量符號 ''' * :0次或多次 ? :0次或1次 + :至少1次 {m} :重復m次 {m,n} :重復m到n次 {m} :至少重復m次 {m,} :長度的大于等于, {,n} :小于等于 '''# 常用的 匹配字符串 ''' . 匹配任意一個字符(除了\n) [] 匹配列表中的字符 \w 匹配字母、數字、下劃線,即a-z,A-Z,0-9,_ \W 匹配不是字母、數字、下劃線 \s 匹配空白字符,即空格(\n,\t) \S 匹配不是空白的字符 \d 匹配數字,即0-9 \D 匹配非數字的字符 '''這里也有一些特殊字符的展示
比如 十六進制 Unicode碼 \u0000:\uFFFF
ASCII碼 \x00:\xFF,
-
中文字符的 Unicode 范圍 \u4e00-\u9fa5
-
ascii 只能匹配 英文的。 范圍為 0- 255 一共 256 個字符
關于控制字符 \cA-\cZ 對應的是 ascii 中 1-26 的控制字符 。但是 python不支持 \cA 這種寫法
所以不建議 使用 建議使用 十六進制碼 或者 \t 這種寫法(前提是那個字符有類似的寫法)
演示
看完這個應該就能理解我想說的是什么了。
import re str_=""" 中國牛逼 2020-12-12 2020年12月4日19:47:07 """ pat=r'[\n]' pat1=r'[\x0A]' re.findall(pat,str_) re.findall(pat1,str_)匹配某個字符串
# match, 匹配某個字符串 text = 'hello' ret = re.match('he', text) # match 只會匹配前面的字符 ahello 就匹配不到了 print(ret.group()) # group 把提匹配到的字符串提取出來. 點 , 匹配符任意的字符
# 點,匹配符任意的字符 text = 'hello' ret = re.match('.', text) # 但是只能匹配一個字符,但是 不能匹配換行符\n print(ret.group())任意字符不包括換行符
真正的任意字符可以寫成 多種方式 [\w\W] [\s\S] [\d\D] 或者 使用 flags 標志 re.S
任意的數字 \d
# 任意的數字 \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())任意的非數字 \D
# 任意的非數字 \D text = "+a" ret = re.match('\D', text) print(ret.group())\w 匹配的是 a-z 和A-z 以及數字0-9和下劃線
# \w 匹配的是 a-z 和A-z 以及數字0-9和下劃線text = "ab" ret = re.match('\w', text) print(ret.group())\W 匹配 大小寫字母 數字 和 下劃線 以外的字符
# \W 與 \w 相反 匹配的text = "+ab"ret = re.match('\W', text)print(ret.group())*匹配多個字符
# 匹配多個字符# * 星號可以匹配 0個 或者任意多個 字符 text = "abdc" ret = re.match('\d*', text) # 這個 '\d*' 匹配任意多個數字 print(ret.group())# + 加號 匹配一個或者多個字符 text = "+abdc" # 這個 '\w+'' 匹配一個以上 a-z 和A-z 以及數字0-9和下劃線 組成的 字符串 ret = re.match('\w+', text) # 因為 是從開頭開始匹配 ,所以這里會報錯 因為開頭 匹配不到 print(ret.group()) import re print('--------*的使用------------') pattern='\d*' s='123qwe' s='123456qwe' s='qwe' o=re.match(pattern,s) print(o)? 問號 匹配一個或者0個字符
# ? 問號 匹配一個或者0個字符 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個字符
# {m}匹配m個字符 text = "abdc+" ret = re.match('\w{2}', text) # 匹配兩個字符 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個字符
# {m,n}匹配m到n個字符 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} 實現(xiàn) 長度的大于等于, 小于等于
print('---------{m,}-----------') pattern='\d{2,}' s='123qwe' s='123456qwe' s='qwe' o=re.match(pattern,s) print(o) # 表示 空字符串。長度為 0 的字符串。 s = '' o1 = re.match(r'^$', s) print(o1) # 有匹配結果,匹配到空字符串 s = '1' print(o1) # 無匹配結果,返回 None- 指定開放區(qū)間,省略第2個值,保留逗號。例如 a{4, } 匹配4個或更多個連續(xù)的字符a。
脫字號 ^ 以 …開始,
# 脫字號 '^' 以 ...開始, # 放在中括號[]里面 是取反的意思 text = "hello.py" ret = re.search('^h\w*\.py$', text) # match 是從開始去匹配 和 脫字號 是一樣的功能 print(ret.group())'$' 以…結尾
# '$' 以...結尾 text = "pis1@163.com" ret = re.match('\w+@163.com$', text) # match 是從開始去匹配 和 脫字號 是一樣的功能 print(ret.group())'|' 匹配多個字符串或者表達式
# `'|' ` 匹配多個字符串或者表達式 或者的 意思 要么 的意思 text = "http" ret = re.match('(http|https|ftp)$', text) # match 是從開始去匹配 和 脫字號 是一樣的功能 print(ret.group()) # 匹配多個字符串 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之間所有的數字') #匹配0-100之間所有的數字 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)關于 ! 和 ^ 以及 $ 搭配使用
(^|\\s) 就代表 可以是 以 '' 就是沒有字符開始 或者 \s 空白字符開始 的 字符
同理 $ 這就是 以沒有"" 結尾 或者 空字符結尾
[ ] 組合的方式
# [ ] 組合的方式 ,只要,滿足中括號 中的字符,就可以匹配 text = "a" ret = re.match('[a1]', text) # 匹配 a和 1 print(ret.group()) 8.1 text = "0731-88888888"# 特殊字符 需要 -前面轉義 加一個\ \d是數字匹配 寫一個 + 加號 就是匹配到 多個字符 ret = re.match('[\d\-]+', text) print(ret.group())# 8.2 中括號 代替 \d 以及 反斜杠 \w text = "1213" ret = re.match('[^0-9]+', text) # 這個 ^0-9 是 匹配非0-9的字符 前面加了一個脫字號 print(ret.group())# 8.2 中括號 代替 以及 反斜杠 \w text = "1213" ret = re.match('[a-zA-Z0-9_]', text) # 這個 ^0-9 是 匹配非0-9的字符 print(ret.group()) # 8.2 中括號 代替 以及 反斜杠 \W text = "*" ret = re.match('[^a-zA-Z0-9_]', text) # 這個 ^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)+ 號 的使用
print('--------+的使用------------') pattern='\d+' # s='123qwe' # s='1qwe' # s='123456qwe' s='qwe' o=re.match(pattern,s) print(o)轉義字符的使用
當然 我們也可以使用 raw 原生字符 s=r'\t123' 類似這樣的語法 會經常 看到。
# 轉義字符的使用 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) # 轉義字符 和 原生字符串 text = "apple price is $299" ret = re.search("\$\d+", text) # 提取價格 \ 轉義 \$ 只想 讓他作為 普通字符串 print(ret.group())# 原生字符串 text = "\\n" # python 中的 轉義字符 把 換行符 轉換成一個 普通反斜杠 text = r"\n" # 前面加一個r 就是原生的意思 r 就是 raw 原生的意思 別的 正則里面也可以使用 print(text)# 反斜杠 正則和 python 的 \ 反斜杠 都是 轉義 ,所以 想要打印出反斜杠 需要4 個反斜杠text = '\c' # 這里在python 語言中 '\\n'='\n' # python中\(zhòng)\\\c => \\c # 正則中 \\c= > \c # ret = re.match('\\\\c', text) # 轉義 ret = re.match(r'\\c', text) # 原生字符串的方式 print(ret.group())常用方法
常用查詢,主要功能函數
re.search
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參數的使用') s='hello python' pattern='Hello' o=re.match(pattern,s,flags=re.I) # re.I # re.IGNORECASE 這兩個是一樣的。 # 都是忽略大小寫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'] # 這里是這個 match 對象的屬性In [5]: print(o.group()) #返回匹配的字符串 helloIn [6]: print(o.span()) # 匹配到的字符串的 索引范圍 (0, 5)In [7]: print(o.start()) # 匹配到的字符的 開始位置 0In [8]: print('flags參數的使用') flags參數的使用In [9]: s='hello python'...: pattern='Hello'...: o=re.match(pattern,s,flags=re.I)# re.I # re.IGNORECASE 這兩個是一樣的。 # 都是忽略大小寫 In [10]:In [10]: print(o) <_sre.SRE_Match object; span=(0, 5), match='hello'>In [11]: print(o.group()) hellore.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 分割函數 text = "hello&world ni hao" ret = re.split('[^a-zA-Z]', text) # 以非英文字母為分割 符號 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 # 這是一個國外電話號碼' #將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(),但返回一個元組 (new_string, number_of_subs_made) .
import re phone='2004-959-559 # 這是一個國外電話號碼' #將phone中的注釋去掉 pattern=r'#.*$' print('---------subn-----------') result=re.subn(pattern,'',phone) print(result) print(result[0]) print(result[1])re.compile
re.escape(pattern) 處理轉義字符
re.escape(pattern)
在中轉義特殊字符 模式 . 如果要匹配可能包含正則表達式元字符的任意文本字符串,則此選項非常有用。例如:
常用方法(函數)sub 案例
import re # 實際的案例 替換 函數 html = ''' <dd class="job_bt"><h3 class="description">職位描述:</h3><div class="job-detail"><p>崗位職責:</p> <p>1、完成對復雜網站的數據抓取和交互模擬;</p> <p>2、通過各種渠道或方式對相關網站進行抓取;</p> <p>3、不斷完善并維護相關網站的抓取,使之穩(wěn)定運行,核心邏輯必須有單元測試;</p> <p>4、善于靈活運用各種非爬蟲技術解決爬蟲相關問題;</p> <p>5、隨時響應并解決突發(fā)問題;</p> <p>6、完成領導交辦的其他工作。</p> <p><br></p> <p>任職要求:</p> <p>1、本科以上學歷,三年以上網站抓取經驗,有電商網站、秒殺相關抓取經驗;</p> <p>2、有較強的網站分析能力,熟知各種反爬措施及相關解決辦法</p> <p>技能要求;</p> <p>3、熟練使用eventlet、gevent、requests、selenium等技術實現(xiàn)高并發(fā)穩(wěn)定抓取;</p> <p>4、熟練使用消息隊列(MQ)、celery等異步框架實現(xiàn)分布式任務處理;</p> <p>5、熟知HTTP、TCP、Socket等底層知識;</p> <p>6、熟練掌握Fiddler、Http debugger等抓捕工具;</p> <p>7、熟悉MySQL、MongoDB基本使用;</p> <p>8、熟悉Scapy,熟悉Javascript,有一定的分析能力;</p> <p>9、能使用mock進行單元測試;</p> <p>10、善于溝通、有團隊協(xié)作精神。</p> <p><br></p> <p>我們的團隊成員都是80后、90后,我們是充滿激情和干勁的團隊,我們是有夢想有追求的團隊……</p> <p>如果你有滿腔熱忱,如果你不想碌碌無為,如果你想通過自己的努力成為合伙人……</p> <p>來吧!朋友,加入我們,我們會給你釋放夢想的平臺,我們會讓你的美夢成真……</p> <p>期待有為的你加入!!!</p> <p> </p> <p>為了讓我們的小伙伴能夠快樂、健康的在一起為了夢想而努力,我們提供了以下多種福利及文化活動:</p> <p>1、每天工作8小時,彈性工作時間;</p> <p>2、公司年度健康體檢,小伙伴在為公司默默奉獻的同時,公司也時刻關注著他們的健康。</p> <p>3、量身定制的培訓計劃,讓員工在我們細致入微的幫助下更快的融入團隊。</p> <p>4、豐富的企業(yè)文化活動:</p> <p>? 每天:美味的零食和飲品;</p> <p>? 每兩周:組織大家去打乒乓球、羽毛球,小伙伴的健康是我們一直關注的;</p> <p>? 每月:家人生日會(給每位壽星唱著生日快樂歌,分享美味可口的蛋糕,盡享溫馨時刻);</p> <p>? 季度:團隊建設、拓展活動;</p> <p>? 年度:大型年會(辛苦了一年的匯游科技家人,一起收獲一起分享)。</p> <p>5、每年1次調薪,兩次豐厚的績效獎金,付出與回報永遠成正比哦。</p> <p>6、節(jié)日禮品、生日禮品、結婚生子禮金等。</p> <p>7、每天午餐補助,每月全勤獎勵。</p> <p>…………</p> <p> </p> <p> </p> <p>匯游科技祝您面試成功!</p></div></dd> '''ret = re.sub('<.+?>', '', html) # 非貪婪 模式 ,把 非標簽的數據替換掉了 print(ret)re匹配到的對象
比如match 或者search 匹配到 的對象 也就是 這些函數的 返回值
可以這樣理解。
<_sre.SRE_Match object; span=(0, 11), match='33.33.33.33'> 這個就是一個返回對象 。
match對象
匹配對象
返回對象的常用屬性
返回對象的常用方法
貪婪模式和非貪婪模式
re 默認是貪婪模式
如何非貪婪模式?
*?, +?, ?? 這些符號 就代表非貪婪 模式 (也叫最小匹配操作符)
比如 你使用 (.*?) 匹配任意字符 但是 是非貪婪 模式 。 只匹配最少的數據。
關于分組
(...)
匹配圓括號內的任何正則表達式,并指示組的開始和結束;組的內容可以在執(zhí)行匹配后檢索,稍后在字符串中與 \number 特殊順序,如下所述。匹配文字 '(' 或 ')' 使用 \( 或 \) 或將它們括在字符類中: [(] , [)] .
\number
匹配同一號碼組的內容。組從1開始編號。例如, (.+) \1 'the the' 或 '55 55' ,但不匹配 'thethe' (注意組后的空格)。
()分組 \num 別名
import re# 示例 1 匹配座機號碼 使用 ( ) 括號 分組 print('匹配座機號碼') # 匹配座機號碼 區(qū)號{3,4}-電話號碼{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() 返回的是字符串 所以這種方式 就是類似元組 切片 索引訪問 字符串。 # print(o.groups()[1])print('匹配出網頁標簽內的數據') # 示例 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 # 正確示范,()有分組作用,正則表達式中\(zhòng)1可以取到分組的第一個 import rehtml_str = "<h1>hahaha</h1>" ret = re.match(r"<(\w*)>.*</\1>", html_str) print(ret.group())
# ( ) \1 # 正確示范,()有分組作用,正則表達式中 \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標簽 .+ 匹配 起別名 # <(?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)
通過觀察可以發(fā)現(xiàn) 取了別名 就有了 groupdict 了
# -------------------------------(?P<name>) #命名的格式 (注意P是大寫的) (?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) # 將整個字符串提取出來括號里是分組的意思print(ret.group()) # 整個正則表達式 就是一個 大的分組,可以寫0或者不寫 都是可以的 print(ret.group(1)) # 第一個分組 print(ret.group(2)) # 第二個分組 print(ret.group(1, 2)) # 兩個分組 拿出來 print(ret.groups()) # 所有 的子分組 都拿出來
(...)\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 開始編碼
group(0) 等價于 group() 返回整個 匹配 。
groups
返回一個包含匹配的所有子組的元組,從1到模式中的所有組。這個 default 參數用于沒有參與匹配的組;它默認為 None .
關于分組的 一些實際 例子
分組的反向引用 ( 就是那個 \1)
import re import requests pat="<(\w+)>(.+)<\/\1>" # 基本套路 不過對于一些復雜的 html 標簽無法 提取 res=requests.get("http://www.baidu.com") res.encoding='utf-8' html=res.textpat=r"<(head)>(.+)</\1>" # 稍加 修改 re.findall(pat,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><title>百度一下,你就知道</title>')]pat=r"<(div)\s*.*?>(.+)</\1>" # 再次修改 re.findall(pat,html) # 返回結果 # [('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;tpl=mn&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&tpl=mn&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;">更多產品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>關于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必讀</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意見反饋</a> 京ICP證030173號 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> ')]pat=r"<(\w+)\s*.*?>(.+)</\1>" # pat="<(\w+)>(.+)<\/\1>" 完成我在一開始想用這個操作的事情。 re.findall(pat,html) # 返回結果 #[('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><title>百度一下,你就知道</title></head> <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;tpl=mn&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&tpl=mn&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;">更多產品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>關于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必讀</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意見反饋</a> 京ICP證030173號 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> ')]一些運行效果
常用的 flags
re.A
re.ASCII
制作 \w , \W , \b , \B , \d , \D , \s 和 \S 只執(zhí)行ASCII匹配,而不是完全Unicode匹配。這只對Unicode 模式有意義,而對于字節(jié)模式則被忽略。對應于內聯(lián)標志 (?a) .
請注意,為了向后兼容, re.U 標志仍然存在(及其同義詞 re.UNICODE 及其嵌入的對應項 (?u) ,但在python 3中這些是多余的,因為字符串的匹配默認為Unicode(字節(jié)不允許使用Unicode匹配)。
re.DEBUG
顯示有關已編譯表達式的調試信息。沒有對應的內聯(lián)標志。
re.I
re.IGNORECASE
執(zhí)行不區(qū)分大小寫的匹配; 對應于內聯(lián)標志 (?i) .
re.M
re.MULTILINE
指定時,模式字符 '^' 匹配字符串的開頭和每行的開頭(緊跟每行換行符);以及模式字符 $ 匹配字符串的結尾和每行的結尾(緊接著每行換行符的前面)。默認情況下, '^' 僅在字符串的開頭匹配,并且 '$' 只在字符串的末尾,在字符串末尾的換行符(如果有)之前。對應于內聯(lián)標志 (?m) .
其實一句話 就是 換行符為邊界
比如 22\n3322\n3322\n33 如果我要獲取 以某某開頭的兩位數字字符。 以換行符為邊界。 那就是 22 33 33 33
可以理解為 行首 行尾 的概念。
而不是字符串的首尾。
如果flags 用 re.M 但是想要 獲取字符串首部 那就是 \A 需要寫在開頭 ,獲取字符串尾部是 \Z 需要寫在后面
import re pat=r"(?m)^\d{2}" str_="22\n3322\n3322\n33" re.findall(pat,str_)關于 \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
使'.'特殊字符完全匹配任何字符,包括換行符;如果沒有此標志, '.' 會匹配任何東西 除了 換行符對應于內聯(lián)標志 (?s) .
re.X
re.VERBOSE
此標志允許您編寫看起來更好、更可讀的正則表達式,方法是允許您直觀地分隔模式的邏輯部分并添加注釋。
指定多個 flags 的方式
re.I | re.M 用 | 表達符 表示 flags 被設置為了 re.I 和 re.M
或者使用內聯(lián)的方式 (?im) 并且這個 標志要寫在 最開始的位置。 否則會報 警告信息
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)一些不常見的匹配符號
(?P=name)
- (?P< name >)
- 命名的格式 (注意P是大寫的)
- (?P=name)
- 取值的格式
對命名組的后向引用;它與先前命名組匹配的任何文本匹配 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())(?#...)
注釋;括號的內容被忽略。
相當于沒寫。 就可以理解為 就是 寫的注釋
正則 斷言匹配
斷言的組成之一是邊界。對于文本、詞或模式,邊界可以用來表明它們的起始或終止部分(如向前斷言,向后斷言以及條件表達式)。
(?=...) => 匹配 某字符跟隨某某字符 ,匹配前者。
匹配如果 ... 匹配下一個,但不使用任何字符串。這叫A lookahead assertion 前瞻性斷言或者說 先行斷言 . 例如, Isaac (?=Asimov) 將匹配 'Isaac ' 只有在后面跟著 'Asimov' .
向前斷言:例如,對于 Jack(?=Sprat),“Jack”在跟有“Sprat”的情況下才會得到匹配./Jack(?=Sprat|Frost)/ “Jack”后跟有“Sprat”或“Frost”的情況下才會得到匹配。不過, 匹配結果 不包括 “Sprat”或“Frost”。
所謂的先行是指的 匹配的東西先行
條件后行。
tips: 記憶小技巧 有箭頭的斷言 條件都寫在 前面的。
所以 都是后行。
先行斷言 匹配的模式字符寫在 前面
后行斷言 匹配的模式字符串寫在后面
斷言就是指定條件。 不匹配字符。
In [81]: pat=r'Isaac (?=Asimov)'In [82]: p=re.compile(pat)In [85]: p.search("Isaac Asimovv") # 可以理解為 匹配 以某字符串結尾的 字符。 Out[85]: <_sre.SRE_Match object; span=(0, 6), match='Isaac '>
(?!...)=> 匹配 某字符串 后面沒跟著某某字符。匹配前者。
匹配如果 ... 與下一個不匹配。這是一個 negative lookahead assertion 否定超前斷言 向前否定斷言. 例如, Isaac (?!Asimov) 將匹配 'Isaac ' 只要后面不是 'Asimov' .
需要注意 ()里 這個是條件 是不會被匹配到的
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") # 匹配 # 可以理解為 匹配 不以 某字符串 結尾的 字符 Out[78]: <_sre.SRE_Match object; span=(0, 6), match='Isaac '>(?<=...) => 匹配前面是某某字符的某字符。匹配后者
如果字符串中的當前位置前面有匹配項,則匹配 ... 在當前位置結束。這叫A positive lookbehind assertion 肯定斷言 或者叫做 向后肯定斷言 .
(?<=abc)def 將在中找到匹配項 'abcdef' ,因為lookback將備份3個字符并檢查包含的模式是否匹配。
包含的模式必須只匹配某個固定長度的字符串,這意味著 abc 或 a|b 是允許的,但是 a* 和 a{{3,4}} 不是
請注意,以正的lookbehind斷言開頭的模式在被搜索的字符串的開頭將不匹配;您很可能希望使用 search() 函數而不是 match() 功能:
需要注意 ()里 這個是條件 是不會被匹配到的
import re # 前面 有 abc 那么 我就 匹配 def m = re.search('(?<=abc)def', 'abcdef') # 可以理解為以某字符串開頭的 字符 m.group(0)# 輸出 'def'# 此示例查找連字符后的單詞: # 前面有連字符 那么我就匹配后面的 這個字符 m = re.search(r'(?<=-)\w+', 'spam-egg') m.group(0)'egg'(?<!...)=> 匹配 前面不是某某字符我就匹配某字符。 匹配后者
如果字符串中的當前位置前面沒有匹配項,則匹配 … . 這叫A negative lookbehind assertion 向后否定斷言.
與正查找斷言類似,包含的模式必須只匹配某些固定長度的字符串。
以負的lookbehind斷言開頭的模式可能在要搜索的字符串的開頭匹配。
需要注意 ()里 這個是條件 是不會被匹配到的
In [87]:...: import re# 前面 不是 adc 那么我就匹配后面的字符...: m = re.search('(?<!abc)def', 'abcdef') # 未匹配到任何東西 In [90]:...: import re...: m = re.search('(?<!abc)def', 'bcdef') # 可以理解為不以某某開頭的字符 后面的字符In [91]: m.group() Out[91]: 'def'(?(id/name)yes-pattern|no-pattern)
如果給定的組 id 或 name 指向的組 有值 將嘗試 使用 yes-pattern 匹配一些字符 ,否則嘗試使用 no-pattern 匹配一些字符 。 no-pattern 是可選的,可以省略。
特殊序列包括 '\' 以及下面列表中的一個字符。如果普通字符不是一個ASCII數字或一個ASCII字母,那么得到的RE將與第二個字符匹配。例如, \$ 與 '$'匹配 .
相信 看完 這幾張圖 然后 自己實驗 一下 所有人都能理解這是什么意思。
- pat="(\w+@\w+(?:\.\w+)+)"
- pat="(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|>$)"
- s1 的分組 id為1 的 匹配了 < 說明有值 那么match=<user@host.com 使用 yes 模式 嘗試匹配> 因為 s1是 user@host.com 所以匹配成功
- s3的分組id 為1 的 組 值為None 所以使用 no 模式 。然后 s3=user@host.com> 所以no 模式我寫的 匹配 > 也匹配到了。
常用正則速查
/這里是正則/
js 中正則就是 寫在 // 下劃線中的
示例(比如我要驗證用戶名)
import re pat='^[a-z0-9_-]{3,16}$' str="你要驗證的字符串" re.match(pat,str)如果已有的正則 不符合你的 要求
記得自己修改一下哦
| /^[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]+$/ |
總結
以上是生活随笔為你收集整理的1_正则表达式(python)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 编译安装virtualbox 3.1.2
- 下一篇: 与局域网内计算机互联有关的IPX协议