正则就是用一些具备特殊含义的符号组合到一块儿(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在Python中)它内嵌在Python中,并经过 re 模块实现。正则表达式模式被编译成一系列的字节码,而后由用 C 编写的匹配引擎执行。php
正则表达式就是字符串的匹配规则,python里应用的是re模块。html
文件“嫩模联系方式”内容以下:java
姓名 地区 身高 体重 电话 况咏蜜 北京 171 48 13651054608 王心颜 上海 169 46 13813234424 马纤羽 深圳 173 50 13744234523 乔亦菲 广州 172 52 15823423525 罗梦竹 北京 175 49 18623423421 刘诺涵 北京 170 48 18623423765 岳妮妮 深圳 177 54 18835324553 贺婉萱 深圳 174 52 18933434452 叶梓萱 上海 171 49 18042432324 杜姗姗 北京 167 49 13324523342
从文件中取出全部的手机号:python
import re f = open("嫩模联系方式", "r") # 取文件中手机号码,字符匹配传统方法 # contacts = [] # for line in f: # name,region,height,weight,phone = line.split() # if phone.isdigit(): # # print(phone) # contacts.append(phone) # print(contacts) data = f.read() contacts = re.findall("[0-9]{11}", data) # 将要匹配的字符规律,提炼为一个公式 print(contacts) """ ['13651054608', '13813234424', ..., '18042432324', '13324523342'] """
手机号是有规则的,都是数字且是11位,再严格点,就都是1开头,若是能把这样的规则写成代码,直接拿规则代码匹配文件内容将会容易不少c++
'.' 默认匹配除\n以外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行 '^' 匹配字符开头,若指定flags MULTILINE,这种也能够匹配上(r"^a","\nabc\neee",flags=re.MULTILINE) '$' 匹配字符结尾, 若指定flags MULTILINE ,re.search('foo.$','foo1\nfoo2\n',re.MULTILINE).group() 会匹配到foo1 '*' 匹配*号前的字符0次或屡次, re.search('a*','aaaabac') 结果'aaaa' '+' 匹配前一个字符1次或屡次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb'] '?' 匹配前一个字符1次或0次 ,re.search('b?','alex').group() 匹配b 0次 '{m}' 匹配前一个字符m次 ,re.search('b{3}','alexbbbs').group() 匹配到'bbb' '{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb'] '|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC' '(...)' 分组匹配, re.search("(abc){2}a(123|45)", "abcabca456c").group() 结果为'abcabca45' '\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的,至关于re.match('abc',"alexabc") 或^ '\Z' 匹配字符结尾,同$ '\d' 匹配数字0-9 '\D' 匹配非数字 '\w' 匹配[A-Za-z0-9],还包括下划线‘_’ '\W' 匹配非[A-Za-z0-9] 's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t' '(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'}
'.'匹配任意一个字符,默认从头开始找('\n'除外)git
>>> import re >>> s = 'abc1d3e' >>> s 'abc1d3e' >>> re.search('.', s) <_sre.SRE_Match object; span=(0, 1), match='a'> >>> re.search('..', s) <_sre.SRE_Match object; span=(0, 2), match='ab'>
'^'匹配字符开头正则表达式
>>> re.search('^ab', 'hisisig') >>> re.search('^ab', 'abssiif') <_sre.SRE_Match object; span=(0, 2), match='ab'>
'$'匹配结尾app
>>> re.search('b$','bosojb') <_sre.SRE_Match object; span=(5, 6), match='b'>
'*'匹配*前的字符任意次this
>>> re.search('b*','bosojb') <_sre.SRE_Match object; span=(0, 1), match='b'> >>> re.search('o*','booooojb') <_sre.SRE_Match object; span=(0, 0), match=''> >>> re.search('bo*','booooojb') <_sre.SRE_Match object; span=(0, 6), match='booooo'> >>> re.search('bo*','booooojb').group() 'booooo'
'+'匹配字符一次或屡次url
>>> re.search('o+','booooojb') <_sre.SRE_Match object; span=(1, 6), match='ooooo'> >>> re.search('b+','booooojb') <_sre.SRE_Match object; span=(0, 1), match='b'> >>> re.search('.+','booooojb') <_sre.SRE_Match object; span=(0, 8), match='booooojb'> >>> re.search('ab+','booooojabbbb') <_sre.SRE_Match object; span=(7, 12), match='abbbb'>
'?'匹配0次或1次
>>> re.search('ab?','booooojabbbb') <_sre.SRE_Match object; span=(7, 9), match='ab'> >>> re.search('b?','booooojabbbb') <_sre.SRE_Match object; span=(0, 1), match='b'>
'{m}'匹配前一个字符m次
>>> re.search('b{3}','booooojabbbb') <_sre.SRE_Match object; span=(8, 11), match='bbb'> >>> re.search('a{3}','booooojabbbb') >>> re.search('[0-9]{3}','booo2213bb') <_sre.SRE_Match object; span=(4, 7), match='221'>
'{n, m}'匹配前一个字符n到m次
>>> re.search('[a-z]{3}','booo2213bb') <_sre.SRE_Match object; span=(0, 3), match='boo'> >>> re.search('[a-z]{2,5}','booo2213bb') <_sre.SRE_Match object; span=(0, 4), match='booo'> >>> re.search('[a-z]{2}','alex') <_sre.SRE_Match object; span=(0, 2), match='al'> >>> re.search('[a-z]{1,2}','alex') <_sre.SRE_Match object; span=(0, 2), match='al'> >>> re.search('[a-z]{1,2}','a2lex') <_sre.SRE_Match object; span=(0, 1), match='a'> >>> re.search('[a-z]{1,2}','2lex') <_sre.SRE_Match object; span=(1, 3), match='le'>
'|'匹配左或右的字符
>>> re.search('alex|Alex', 'Alex') <_sre.SRE_Match object; span=(0, 4), match='Alex'> >>> re.search('alex|Alex', 'alex') <_sre.SRE_Match object; span=(0, 4), match='alex'> >>> re.search('[a|A]lex', 'alex') # 变化的部分用或【a|A】,实现简写 <_sre.SRE_Match object; span=(0, 4), match='alex'>
'(...)'分组匹配
>>> re.search('[a-z]+', 'alex123213') <_sre.SRE_Match object; span=(0, 4), match='alex'> >>> re.search('([a-z]+)([0-9]+)', 'alex123213').group() 'alex123213' >>> re.search('([a-z]+)([0-9]+)', 'alex123213').groups() ('alex', '123213')
'\'转义
'\A'从字符开头匹配,等同'^'
>>> re.search('\Aalex', 'alexadwwd') <_sre.SRE_Match object; span=(0, 4), match='alex'>
'\Z'匹配字符结尾 等同'$'
'\d'匹配数字0-9
'\d+'贪婪匹配,匹配任意个
>>> re.search('\d','booo2213bb') <_sre.SRE_Match object; span=(4, 5), match='2'> >>> re.search('\d+','booo2213bb') <_sre.SRE_Match object; span=(4, 8), match='2213'>
'\D'匹配非数字
'\D+'贪婪匹配
>>> re.search('\D','booo2213bb') <_sre.SRE_Match object; span=(0, 1), match='b'> >>> re.search('\D+','booo2213bb') <_sre.SRE_Match object; span=(0, 4), match='booo'>
'\w'匹配[A-Za-z0-9]
>>> re.search('\w+','booo2213bb') <_sre.SRE_Match object; span=(0, 10), match='booo2213bb'> >>> re.search('\w','booo2213bb') <_sre.SRE_Match object; span=(0, 1), match='b'>
‘\W’匹配特殊字符
>>> re.search('\W','%$#^&((*hhga') <_sre.SRE_Match object; span=(0, 1), match='%'> >>> re.search('\W+','%$#^&((*hhga') <_sre.SRE_Match object; span=(0, 8), match='%$#^&((*'>
'\s'匹配空白字符
>>> s = 'hssis\nisijsi\njack' >>> print(s) hssis isijsi jack >>> re.search('\s',s) <_sre.SRE_Match object; span=(5, 6), match='\n'> >>> re.search('\s+',s) <_sre.SRE_Match object; span=(5, 6), match='\n'> >>> re.findall('\s+',s) ['\n', '\n']
'(?P<name>...)' 分组匹配
>>> s = '230701200104280028' >>> re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<born_date>\d{8})(?P<seq>\d{4})',s) <_sre.SRE_Match object; span=(0, 18), match='230701200104280028'> >>> re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<born_date>\d{8})(?P<seq>\d{4})',s).groups() ('230', '701', '20010428', '0028') >>> res = re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<born_date>\d{8})(?P<seq>\d{4})',s) >>> res.groupdict() {'province': '230', 'city': '701', 'born_date': '20010428', 'seq': '0028'}
正则匹配的语法有如下几种:
re.split()
>>> s = 'alex22123jack233rain213jinxin5040' >>> re.split('\d',s) # 按数字分割 ['alex', '', '', '', '', 'jack', '', '', 'rain', '', '', 'jinxin', '', '', '', ''] >>> re.split('\d+',s) ['alex', 'jack', 'rain', 'jinxin', ''] >>> s = 'alex22123jack233rain213jinxin5040|mack-Oldboy' >>> re.split('\d+|\|' ,s) # '|'是或 '\|'是转义 ['alex', 'jack', 'rain', 'jinxin', '', 'mack-Oldboy'] >>> s = '8-2*4+1233/3*99*4*232+1232+10*234/14' >>> re.split('[-\*/+]',s) ['8', '2', '4', '1233', '3', '99', '4', '232', '1232', '10', '234', '14']
re.sub(pattern, repl, string, count=0, flags=0) 用于替换匹配的字符串
>>> s = 'alex22123jack233rain213jinxin5040|mack-Oldboy' >>> re.sub('\d+','-',s) 'alex-jack-rain-jinxin-|mack-Oldboy' >>> re.sub('\d+','-',s,count=2) 'alex-jack-rain213jinxin5040|mack-Oldboy'
re.fullmatch(pattern, string, flags=0) 整个字符串匹配成功就返回re object,不然返回None
>>> pattern = re.compile('\w+@\w+\.(com|cn|edu)') >>> pattern.fullmatch('alex@oldboyedu.cn') <_sre.SRE_Match object; span=(0, 17), match='alex@oldboyedu.cn'>
re.compile() 公式编译好了,直接拿去匹配提高效率
>>> pattern = re.compile('\w+@\w+\.(com|cn|edu)') >>> pattern.fullmatch('alex@oldboyedu.cn') <_sre.SRE_Match object; span=(0, 17), match='alex@oldboyedu.cn'>
re.findall(pattern, string, flags=0) match and search 均用于匹配单值
即:只能匹配字符串中的一个,若是想要匹配到字符串中全部符合条件的元素,则须要使用 findall。
import re obj = re.findall('\d+', 'fa123uu888asf') print obj
re.search(pattern, string, flags=0) 根据模型去字符串中匹配指定内容,匹配单个
import re obj = re.search('\d+', 'u123uu888asf') if obj: print obj.group()
>>> re.search('a', 'Alex') >>> re.search('a', 'Alex',re.I) <_sre.SRE_Match object; span=(0, 1), match='A'>
>>> re.search('foo.$','foo1\nfoo2\nfoo3\n') # '$'匹配行尾 <_sre.SRE_Match object; span=(10, 14), match='foo3'> >>> re.search('foo.$','foo1\nfoo2\nfoo3\n',re.M) <_sre.SRE_Match object; span=(0, 4), match='foo1'>
>>> re.search('.','\n') # '.'默认匹配除\n以外的任意一个字符 >>> re.search('.','\n', re.S) <_sre.SRE_Match object; span=(0, 1), match='\n'>
>>> re.search('. #test', 'alex', re.X) <_sre.SRE_Match object; span=(0, 1), match='a'> a = re.compile(r"""\d + # the integral part \. # the decimal point \d * # some fractional digits""", re.X) b = re.compile(r"\d+\.\d*")
import re # 提取python key = "javapythonc++php" re.findall("python", key)[0] """ python """ # 提取出hello world key = "<html><h1>hello world</h1></html>" re.findall('<h1>hello world</h1>', key) """ ['<h1>hello world</h1>'] """ # 提取170 string = "我喜欢身高为170的女孩" # re.findall("170", string)[0] re.findall('\d+', string) """ ['170'] """ # 提取出http://和https:// key = 'http://www.baidu.com and https://boob.com' re.findall('https{0,1}', key) # {}前的字符出现0次或1次 """ ['http', 'https'] """ # 提取出hit. key = "bobo@hit.edu.com" re.findall("h.*\.", key) # .表示任意字符(\n除外);*表示匹配0个或多个;\表示对.转义 """ ['hit.edu.'] """ # 贪婪模式:根据正则表达式尽量多地提取数据。 # 切换为非贪婪模式,加一个"?" re.findall("h.*?\.", key) """ ['hit.'] """ # 匹配sas和saas key = "saas and sas and saaas" re.findall('sa{1,2}s', key) # 匹配1-2次由前面表达式定义的片断 """ ['saas', 'sas'] """ # 匹配i开头的行 re.S:基于单行匹配 re.M:基于多行匹配 string = '''fall in love with you i love you very much i love she i love her''' re.findall("^i.*", string, re.M) """ ['i love you very much', 'i love she', 'i love her'] """ # 匹配全部的行 string = """<div>静夜思 床前明月光 疑是地上霜 举头望明月 低头思故乡 </div>""" re.findall('<div>.*</div>', string, re.S) """ ['<div>静夜思\n床前明月光\n疑是地上霜\n举头望明月\n低头思故乡\n</div>'] """
import requests import re import os # 指定url url = 'http://www.qiushibaike.com/pic/' headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36" } # 发送请求 response = requests.get(url=url, headers=headers) # 获取页面数据 page_text = response.text # 进行数据解析 # img_list存储的是当前页面中全部图片的url,re.S单行匹配做用到页面全部代码中 img_list = re.findall('<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>', page_text, re.S) # print(img_list) """ ['//pic.qiushibaike.com/system/pictures/12126/121261720/medium/4C3EABFQBQHAM0HL.jpg', '//pic.qiushibaike.com/system/pictures/12126/121261695/medium/R0FRTN0NZHFGR154.jpg', ......] """ # 建立一个存储图片数据的文件夹 if not os.path.exists("./images"): os.mkdir('images') # 建立文件夹 # 给图片连接拼接协议头,得到完整的图片地址 for url in img_list: img_url = 'https:' + url # 持久化存储:存储的是图片的数据,不是Url # .content获取图片二进制数据值 img_data = requests.get(url=img_url, headers=headers).content # 图片名称 img_name = url.split('/')[-1] # url根据/切分,得到的最后一个元素值 img_path = 'images/' + img_name # 保存路径 with open(img_path, 'wb') as fp: fp.write(img_data) print(img_name + '写入成功')
执行成功后,控制台打印图片写入信息。同时能够在images文件夹中查看图片内容。