一、什么是正则?

  正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

  正则表达式就是字符串的匹配规则,python里应用的是re模块。

  文件“嫩模联系方式”内容如下:

姓名        地区    身高    体重    电话
况咏蜜 北京 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

  从文件中取出所有的手机号:

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开头,如果能把这样的规则写成代码,直接拿规则代码匹配文件内容将会容易很多

二、常用表达式规则

'.'     默认匹配除\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'除外)

>>> 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'>

  '$'匹配结尾

>>> re.search('b$','bosojb')
<_sre.SRE_Match object; span=(5, 6), match='b'>

  '*'匹配*前的字符任意次

>>> 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'

  '+'匹配字符一次或多次

>>> 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=''>

  '{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', '')

  '\'转义

  '\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=''>
>>> re.search('\d+','booo2213bb')
<_sre.SRE_Match object; span=(4, 8), match=''>

  '\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 = ''
>>> 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=''>
>>> re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<born_date>\d{8})(?P<seq>\d{4})',s).groups()
('', '', '', '')
>>> res = re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<born_date>\d{8})(?P<seq>\d{4})',s)
>>> res.groupdict()
{'province': '', 'city': '', 'born_date': '', 'seq': ''}

三、正则匹配语法

  正则匹配的语法有以下几种:

  • re.match 从头开始匹配
  • re.search 匹配包含
  • re.findall 把所有匹配到的字符放到以列表中的元素返回
  • re.split 以匹配到的字符当做列表分隔符
  • re.sub 匹配字符并替换
  • re.fullmatch 全部匹配

  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)
['', '', '', '', '', '', '', '', '', '', '', '']

  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()

四、正则Flags标志符

1、Flags标志符

  • re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
  • M(MULTILINE): 多行模式,改变'^'和'$'的行为
  • S(DOTALL): 改变'.'的行为,make the '.' special character match any character at all, including a newline; without this flag, '.' will match anything except a newline.
  • X(re.VERBOSE) 可以给你的表达式写注释,使其更可读,下面这2个意思一样

2、re.I——忽略大小写

>>> re.search('a', 'Alex')
>>> re.search('a', 'Alex',re.I)
<_sre.SRE_Match object; span=(0, 1), match='A'>

3、re.M——改变收尾匹配行为

>>> 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'>

4、re.S——改变'.'的行为;基于单行匹配

>>> re.search('.','\n')  # '.'默认匹配除\n之外的任意一个字符
>>> re.search('.','\n', re.S)
<_sre.SRE_Match object; span=(0, 1), match='\n'>

5、re.X——允许给表达式写注释,使其可读;基于多行匹配

>>> 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*")

五、findall()方法使用示例

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文件夹中查看图片内容。

  

re模块——正则表达式操作的更多相关文章

  1. 【Python开发】Python之re模块 —— 正则表达式操作

    Python之re模块 -- 正则表达式操作 这个模块提供了与 Perl 相似l的正则表达式匹配操作.Unicode字符串也同样适用. 正则表达式使用反斜杠" \ "来代表特殊形式 ...

  2. Python之re模块 —— 正则表达式操作

    这个模块提供了与 Perl 相似l的正则表达式匹配操作.Unicode字符串也同样适用. 正则表达式使用反斜杠" \ "来代表特殊形式或用作转义字符,这里跟Python的语法冲突, ...

  3. Python中的re模块--正则表达式

    Python中的re模块--正则表达式 使用match从字符串开头匹配 以匹配国内手机号为例,通常手机号为11位,以1开头.大概是这样13509094747,(这个号码是我随便写的,请不要拨打),我们 ...

  4. python 正则表达式操作

    正则表达式操作  本模块提供了类似于Perl的正则表达式匹配操作.要匹配的模式和字符串可以是Unicode字符串以及8位字符串. 正则表达式使用反斜杠字符('\')来表示特殊的形式或者来允许使用特殊的 ...

  5. ansible模块文件操作

    Ansible常用模块文件操作 [root@tiandong etc]# ansible-doc -l   列出ansible所支持的模块 [root@tiandong ~]# ansible-doc ...

  6. JAVA基础学习之IP简述使用、反射、正则表达式操作、网络爬虫、可变参数、了解和入门注解的应用、使用Eclipse的Debug功能(7)

    1.IP简述使用//获取本地主机ip地址对象.InetAddress ip = InetAddress.getLocalHost();//获取其他主机的ip地址对象.ip = InetAddress. ...

  7. thinkphp中模块和操作映射

    模板和操作映射功能是3.1.2版本支持的对模块和操作设置的映射机制,由于可以通过改变配置动态改变(实际真正改变,并非别名)URL访问地址,加强了应用的安全性,而且,映射机制具有URL不区分大小写访问的 ...

  8. thinkphp使用模块/控制器/操作访问时出现No input file specified.解决方式

    thinkphp使用 http://serverName/index.php/模块/控制器/操作 访问时,出现了 No input file specified. 的错误 解决办法: 一: 开启cgi ...

  9. python OS 模块 文件目录操作

    Python OS 模块 文件目录操作 os模块中包含了一系列文件操作的函数,这里介绍的是一些在Linux平台上应用的文件操作函数.由于Linux是C写的,低层的libc库和系统调用的接口都是C AP ...

随机推荐

  1. 18、OpenCV Python 简单实现一个图片生成(类似抖音生成字母人像)

    __author__ = "WSX" import cv2 as cv import numpy as np def local_threshold(img): #局部阈值 gra ...

  2. zabbix 3.0 快速安装文档

    下载地址:http://www.zabbix.com/download.php 官方文档:https://www.zabbix.com/documentation/3.0/manual/install ...

  3. 条目十四《使用reserve来避免不必要的重新分配》

    条目十四<使用reserve来避免不必要的重新分配> 使用vector和string的插入元素的时候,我们是不用担心内存问题的(只要不超过容器的max_size).因为底层有分配子管理内存 ...

  4. fiddler使用——配置抓取https,出现提示“禁用解密”“单击配置”

    自己在设置fiddler抓https的时候,浏览器总是提示:此证书不受信任:中午没午睡下午一直昏沉沉的,弄了好久,终于想起来是证书的问题:度娘有个不错的答案,这里分享一下!给以后有相同问题的朋友,也同 ...

  5. Sql server 千万级大数据SQL查询优化的几点建议

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  6. SQL里的real类型和tinyint类型在C#里分别对应类型

  7. javascrip 中排序的函数怎么理解

    其中s是数组[888,2222,9,4]:我不明白sort函数中参数是如何作用的,function中的a和b又是干什么的? 那个function的作用就是比较两个数的大小用的,然后返回结果的正负作为排 ...

  8. Win10 修改 开始 菜单样式..

    因为不是平板,所以改成了这个样子 下面说步骤... 打开 菜单栏位置... 将快捷方式 拷贝到 里面 来... 快捷方式 以 #开头.是为了 让其排列在最前面.... 快捷方式有个技巧...快捷方式  ...

  9. JAVA数据结构--冒泡排序

    冒泡排序(英语:Bubble Sort,台湾另外一种译名为:泡沫排序)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行 ...

  10. 洛谷 P3267 [JLOI2016/SHOI2016]侦察守卫(树形dp)

    题面 luogu 题解 树形\(dp\) \(f[x][y]表示x的y层以下的所有点都已经覆盖完,还需要覆盖上面的y层的最小代价.\) \(g[x][y]表示x子树中所有点都已经覆盖完,并且x还能向上 ...