一、破解密碼
1. 排列
代碼演示:
import itertools #1异赫。排列 1,2,3 # 從n個(gè)不同的元素中取出m(m <= n)個(gè)元素,按照一定的順序排成一列 #m == n,全排列(permutations) # 參數(shù):可迭代對(duì)象返敬,個(gè)數(shù) """ 1 ,2 ,3 123 321 231 312 ... """ result1 = itertools.permutations([1,2,3,4], 1) print(result1) list = list(result1) print(list) print(len(list)) """ 總結(jié): 4-1 4 4-2 12 4-3 24 4-4 24 排列的可能性:n! / (n-m)! """
2.組合
代碼演示:
import itertools #組合:從n個(gè)不同的元素中取出m個(gè)元素,不重復(fù) result2 = itertools.combinations([1,2,3,4],3) print(result2) list = list(result2) print(list) print(len(list)) """ 4-4 1 4-3 4 4-2 6 4-1 4 組合的可能性:n! / (m! * (n -m)!) """
3.排列組合
代碼演示:
import itertools #求笛卡爾積 list = list(itertools.product("0123456789qwertyuioplkjhgfdsazxcvbnm",repeat=3)) print(list) print(len(list))
二遂庄、正則表達(dá)式
1.引入案例
代碼演示:
import re #regular Expession regex #需求:判斷一個(gè)qq號(hào)是否是合法的 """ 分析: 1.全數(shù)字 2.位數(shù):5~11 3.第一位數(shù)字不能為0 """ def checkQQ(str): #尋找條件推翻假設(shè) try: #判斷是否是全數(shù)字 num = int(str) #判斷位數(shù) if len(str) <= 5 or len(str) >= 11: return False #判斷開頭是否為0 if str[0] == "0": return False except ValueError as e: return False return True print(checkQQ("6725675785678657")) #使用正則表達(dá)式實(shí)現(xiàn)上面的需求 result = re.match(r"[1-9]\d{4,10}","6725675786574657") print(result)
2.概述
正則表達(dá)式【Regular Expression】,簡(jiǎn)寫為regex劲赠,RE涛目,使用單個(gè)字符串來(lái)描述一系列具有特殊格式的字符串
功能:
? a.搜索
? b.替換
? c.匹配
使用情景:
? 爬蟲
? 驗(yàn)證手機(jī)號(hào),驗(yàn)證郵箱凛澎,密碼【用戶名】
3.使用規(guī)則
3.1匹配單個(gè)數(shù)字或者字符
代碼演示:
import re """ ----------匹配單個(gè)字符與數(shù)字--------- . 匹配除換行符以外的任意字符 [0123456789] []是字符集合霹肝,表示匹配方括號(hào)中所包含的任意一個(gè)字符 [good] 匹配good中任意一個(gè)字符 [a-z] 匹配任意小寫字母 [A-Z] 匹配任意大寫字母 [0-9] 匹配任意數(shù)字,類似[0123456789] [0-9a-zA-Z] 匹配任意的數(shù)字和字母 [0-9a-zA-Z_] 匹配任意的數(shù)字塑煎、字母和下劃線 [^good] 匹配除了good這幾個(gè)字母以外的所有字符沫换,中括號(hào)里的^稱為脫字符,表示不匹配集合中的字符 [^0-9] 匹配所有的非數(shù)字字符 \d 匹配數(shù)字最铁,效果同[0-9] \D 匹配非數(shù)字字符讯赏,效果同[^0-9] \w 匹配數(shù)字,字母和下劃線,效果同[0-9a-zA-Z_] \W 匹配非數(shù)字冷尉,字母和下劃線漱挎,效果同[^0-9a-zA-Z_] \s 匹配任意的空白符(空格,回車网严,換行识樱,制表,換頁(yè))震束,效果同[ \r\n\t\f] \S 匹配任意的非空白符,效果同[^ \f\n\r\t] """ #[] :只匹配其中的一位 # - :表示一個(gè)區(qū)間 #1. #1.1編譯正則表達(dá)式返回對(duì)象 #使用r可以不考慮轉(zhuǎn)義問(wèn)題 pattern = re.compile(r"[abcd]") #正則表達(dá)式 [a-d] #1.2使用正則表達(dá)式匹配字符串当犯,成功返回對(duì)象垢村,并攜帶匹配之后額結(jié)果,如果匹配失敗則返回None ret = pattern.match("dhello") #需要被匹配的字符串 print(ret) print(ret.group()) #取出匹配到的分組 #2. pattern = re.compile(r"[s-z]") ret = pattern.match("xhello") print(ret) print(ret.group()) #3 pattern = re.compile(r"[0-9]") ret = pattern.match("5hello") print(ret) print(ret.group()) #4 pattern = re.compile(r"[0-9a-zA-Z]") ret = pattern.match("8hello") print(ret) print(ret.group()) #5 ^:脫字符【】否定的含義 pattern = re.compile(r"[^0-9]") ret = pattern.match("chello") print(ret) print(ret.group()) #6 \d:只匹配數(shù)字嚎卫,等同于[0-9] pattern = re.compile(r"\d") ret = pattern.match("4") print(ret) print(ret.group()) #7. \w pattern = re.compile(r"\w") ret = pattern.match("7") print(ret) print(ret.group()) #8 \s pattern = re.compile(r"\s") ret = pattern.match("\t") print(ret) print(ret.group()) #9. .:匹配不到換行符【\n】 pattern = re.compile(r".") ret = pattern.match("\r") print(ret) print(ret.group())
3.2匹配邊界字符
代碼演示:
import re """ --------------錨字符(邊界字符)------------- ^ 行首匹配嘉栓,和在[]里的^不是一個(gè)意思 startswith $ 行尾匹配 endswith \A 匹配字符串開始,它和^的區(qū)別是,\A只匹配整個(gè)字符串的開頭拓诸,即使在re.M模式下也不會(huì)匹配它行的行首 \Z 匹配字符串結(jié)束侵佃,它和$的區(qū)別是,\Z只匹配整個(gè)字符串的結(jié)束,即使在re.M模式下也不會(huì)匹配它行的行尾 \b 匹配一個(gè)單詞的邊界奠支,也就是值單詞和空格間的位置 bounds \B 匹配非單詞邊界 """ #search() 掃描整個(gè)字符串進(jìn)行匹配 print(re.search(r"^to","today is a good day")) print(re.search(r"day$","today is a good day")) #findall() 返回匹配的結(jié)果列表 #re.M 匹配多行 print(re.findall(r"\Ato","today is a good day\ntoday is a good day",re.M)) print(re.findall(r"^to","today is a good day\ntoday is a good day",re.M)) #總結(jié):\A只匹配第一行的行首馋辈,^匹配每一行的行首 #\b匹配邊界【開始和結(jié)尾】,\B匹配的是非邊界【中間】 print(re.search(r"er\b","never")) #er print(re.search(r"er\b","nerve")) #None print(re.search(r"er\B","never")) #None print(re.search(r"er\B","nerve")) #er #match()函數(shù)只檢測(cè)RE是不是在string的開始位置匹配 #search()會(huì)掃描整個(gè)string查找匹配,會(huì)掃描整個(gè)字符串并返回第一個(gè)成功的匹配,也就是說(shuō)match()只有在0位置匹配成功的話才有返回倍谜,如果不是開始位置匹配成功的話迈螟,match()就返回none
3.3匹配多個(gè)字符
代碼演示:
import re """ -------------------匹配多個(gè)字符------------------------ 說(shuō)明:下方的x叉抡、y、z均為假設(shè)的普通字符,n答毫、m(非負(fù)整數(shù))褥民,不是正則表達(dá)式的元字符 (xyz) 匹配小括號(hào)內(nèi)的xyz(作為一個(gè)整體去匹配) x? 匹配0個(gè)或者1個(gè)x x* 匹配0個(gè)或者任意多個(gè)x(.* 表示匹配0個(gè)或者任意多個(gè)字符(換行符除外)) x+ 匹配至少一個(gè)x x{n} 匹配確定的n個(gè)x(n是一個(gè)非負(fù)整數(shù)) x{n,} 匹配至少n個(gè)x x{n,m} 匹配至少n個(gè)最多m個(gè)x。注意:n <= m x{,m} 匹配最多m個(gè) x|y |表示或洗搂,匹配的是x或y """ #()當(dāng)做一個(gè)整體去匹配消返,返回的結(jié)果為一個(gè)列表 print(re.findall(r"(ab)","aaacccaabbbbb")) print(re.findall(r"a?","aaacccaabbbbb")) print(re.findall(r"a*","aaacccaabbbbb")) print(re.findall(r"a+","aaacccaabbbbb")) """ ['a', 'a', 'a', '', '', '', 'a', 'a', '', '', '', '', '', ''] ['aaa', '', '', '', 'aa', '', '', '', '', '', ''] ['aaa', 'aa'] """ #恰好出現(xiàn)n次 print(re.findall(r"a{2}","aaacccaabbbbb")) #至少出現(xiàn)n次 print(re.findall(r"a{2,}","aaacccaabbbbb")) #{m,n}:至少出現(xiàn)m次,至多出現(xiàn)n次 print(re.findall(r"a{2,5}","aaacccaabbbbb")) #表示或 print(re.findall(r"a|b","aaacccaabbbbb")) #[ab]
3.4匹配分組
代碼演示:
import re #匹配分組 #| :或 #() :整體 #search:會(huì)在字符串中從左向左進(jìn)行查找耘拇,如果找到第一個(gè)符合條件的侦副,則停止查找 #正則1|正則2:只要正則1或者正則2中的一個(gè)滿足,則直接按照這個(gè)條件查找 pattern = re.compile("\d+|[a-z]+") ret = pattern.search("123-d223344aa$$aa") #abc123-d223344aa$$aa print(ret.group()) pattern = re.compile("([a-z]\d)+\w+") ret = pattern.search("abc123-d223344aa$$aa") #abc123-d223344aa$$aa print(ret.group())
3.5子模式
代碼演示:
import re #子模式 #() #如果在正則表達(dá)式中出現(xiàn)\1 \2等標(biāo)識(shí)符的時(shí)候驼鞭,那么\1代表從左向右的第一個(gè)()中的內(nèi)容秦驯。。挣棕。被稱為子模式【簡(jiǎn)化正則表達(dá)式】 pattern = re.compile(r"(123)(456)\1\2") #\1 == 123 \2 == 456 ret = pattern.search("123456123456") print(ret.group()) #子模式訪問(wèn) print(ret.group(1)) print(ret.group(2))
3.6貪婪和非貪婪
代碼演示:
import re #貪婪和非貪婪【匹配一位還是匹配多位的區(qū)別】 #+ * :多次匹配【貪婪匹配】 #在+或者*后面添加译隘?則改為非貪婪匹配 result1 = re.search(r"a(\d+)","a23333333b") print(result1) #23333333 result1 = re.search(r"a(\d+?)","a23333333b") print(result1) #2 #特殊情況;如果一個(gè)正則表達(dá)式的前后都有限定條件的時(shí)候,那么則不存在貪婪模式洛心,固耘?將不起作用 result1 = re.search(r"a(\d+)b","a23333333b") print(result1) result1 = re.search(r"a(\d+?)b","a23333333b") print(result1)
3.7模式修正
代碼演示:
import re #模式修正 """ re.I:忽略大小寫模式【ignorecase】 re.M:視為多行模式【more】 re.S:視為單行模式【single】 """ pattern = re.compile(r"^love",re.M) string = """ alove you love her love he """ result1 = pattern.findall(string) print(result1) pattern = re.compile(r"[a-z]+",re.I) result1 = pattern.search("LLLLLLlove") print(result1.group())
4.re模塊中常用功能函數(shù)
代碼演示:
import re #re模塊中常用的函數(shù) #1.compile() str1 = "today is a good day" str2 = r"\w*" pattern1 = re.compile(str2) print(pattern1.findall(str1)) #2.match() result = re.match(r"[1-9]\d{4,10}","6725675786574657") print(result) #3.search() #注意:只要匹配到一個(gè)符合條件的子字符串,則直接返回词身,后面的內(nèi)容不參與搜索 print(re.search(r"\dcom","www.4comnghughs").group()) #4.findall() #注意;返回的結(jié)果為列表 #finditer(): 返回的結(jié)果為可迭代器 iter = re.finditer(r"\d+","12 fjhaehgj 66 fhaj ") print(iter) for i in iter: print(i) #獲取值 print(i.group()) #獲取下標(biāo) print(i.span()) #5.split() :返回一個(gè)列表 s1 = "1one2two3445545three454four56977878five" print(re.split(r"\d+",s1)) print(re.split(r"[0-9]{1,}",s1)) print(re.split(r"[^a-z]+",s1)) s2 = "zhangsan lilei lisi Han Jack" print(re.split(r" +",s2)) s3 = "zhangsan@@@@lilei##########lisi%%%Han&&&&&&&&&&&&&Jack" print(re.split(r"[^a-zA-Z]+",s3)) #6.sub() 替換厅目,返回的是替換之后的字符串 string1 = "today is a good day today is a good da" #用-將空格替換 #參數(shù):舊的字符換【正則表達(dá)式】 新的字符串 原字符串 print(re.sub(r"\s","-",string1)) #subn() 替換,返回一個(gè)元組(新的字符串法严,替換的次數(shù)) print(re.subn(r"\s","-",string1))
5.注意事項(xiàng)
代碼演示:
import re #注意問(wèn)題 #1.match损敷,findall,search之間的區(qū)別 a = re.search(r"[\d]","abc3ab5").group() print(a) #3 b = re.findall(r"[\d]","abc3ab5") print(b) #['3','5'] c = re.match(r"[\d]","abc3") print(c) #None #2.flags的用法【模式修正】 print(re.split("a","1A2a3A4a",re.I)) #['1A2', '3A4', ''] """ split(pattern,string,maxsplit,flags),當(dāng)傳入三個(gè)參數(shù)的時(shí)候深啤,表示只匹配前三個(gè)參數(shù)拗馒,flags不起作用 """ #解決方案:關(guān)鍵字參數(shù) print(re.split("a","1A2a3A4a",flags=re.I)) #3.使用split函數(shù)之后去除"" poem = "床前明月光,疑是地上霜.舉頭望明月,低頭思故鄉(xiāng)溯街。" list1 = re.split(r"[,.诱桂,。]",poem) print(list1) # for item in list1: if item == "": list1.remove("") print(list1) #['床前明月光', '疑是地上霜', '舉頭望明月', '低頭思故鄉(xiāng)']
練習(xí):寫一個(gè)正則表達(dá)式,用來(lái)匹配手機(jī)號(hào)
1.手機(jī)號(hào)必須以1開頭
2.手機(jī)號(hào)第2位只能是3,4,5,7,8,9中的一位
3.手機(jī)號(hào)總共11位數(shù)字
----------匹配單個(gè)字符與數(shù)字---------
. 匹配除換行符以外的任意字符
[0123456789] []是字符集合呈昔,表示匹配方括號(hào)中所包含的任意一個(gè)字符
[good] 匹配good中任意一個(gè)字符
[a-z] 匹配任意小寫字母
[A-Z] 匹配任意大寫字母
[0-9] 匹配任意數(shù)字挥等,類似[0123456789]
[0-9a-zA-Z] 匹配任意的數(shù)字和字母
[0-9a-zA-Z_] 匹配任意的數(shù)字、字母和下劃線
[^good] 匹配除了good這幾個(gè)字母以外的所有字符堤尾,中括號(hào)里的^稱為脫字符肝劲,表示不匹配集合中的字符
[^0-9] 匹配所有的非數(shù)字字符
\d 匹配數(shù)字,效果同[0-9]
\D 匹配非數(shù)字字符,效果同[^0-9]
\w 匹配數(shù)字涡相,字母和下劃線,效果同[0-9a-zA-Z_]
\W 匹配非數(shù)字哲泊,字母和下劃線,效果同[^0-9a-zA-Z_]
\s 匹配任意的空白符(空格催蝗,回車切威,換行,制表丙号,換頁(yè))先朦,效果同[ \r\n\t\f]
\S 匹配任意的非空白符,效果同[^ \f\n\r\t]
--------------錨字符(邊界字符)-------------
^ 行首匹配犬缨,和在[]里的^不是一個(gè)意思
$ 行尾匹配
\A 匹配字符串開始喳魏,它和^的區(qū)別是,\A只匹配整個(gè)字符串的開頭,即使在re.M模式下也不會(huì)匹配它行的行首
\Z 匹配字符串結(jié)束怀薛,它和$的區(qū)別是,\Z只匹配整個(gè)字符串的結(jié)束刺彩,即使在re.M模式下也不會(huì)匹配它行的行尾
\b 匹配一個(gè)單詞的邊界,也就是值單詞和空格間的位置
\B 匹配非單詞邊界
-------------------匹配多個(gè)字符------------------------
說(shuō)明:下方的x枝恋、y创倔、z均為假設(shè)的普通字符,n、m(非負(fù)整數(shù))焚碌,不是正則表達(dá)式的元字符
(xyz) 匹配小括號(hào)內(nèi)的xyz(作為一個(gè)整體去匹配)
x? 匹配0個(gè)或者1個(gè)x
x* 匹配0個(gè)或者任意多個(gè)x(.* 表示匹配0個(gè)或者任意多個(gè)字符(換行符除外))
x+ 匹配至少一個(gè)x
x{n} 匹配確定的n個(gè)x(n是一個(gè)非負(fù)整數(shù))
x{n,} 匹配至少n個(gè)x
x{n,m} 匹配至少n個(gè)最多m個(gè)x畦攘。注意:n <= m
x|y |表示或,匹配的是x或y
---------------特殊-------------------
'''
*? +? x? 最小匹配十电,通常都是盡可能多的匹配知押,可以使用這種解決貪婪匹配
(?:x) 類似(xyz),但不表示一個(gè)組