python 正则表达式

正则表达式是对字符串操作的一种逻辑公式, 简写为regex
作用:
给定一个正则表达式和另一个字符串,我们可以达到如下目的
1.给定的字符串是否符合正则表达式的过滤逻辑(称作‘匹配’)
2.可以通过正则表达式,从字符串中获取我们想要的特定部分

使用场景:
如何判断一个字符串是手机号?
判断邮箱为163或126的所有邮件地址
一个爬虫,得到了一个网页的HTML源码,你只想把hello world提取出来,老办法是对象.find(’’),新办法是用正则表达式

1.正则表达式之match compile search

// 
# python re模块
import re
#match是从头开始匹配,如果头部没有,就返回空
msg='娜扎热巴代斯佟丽娅'
pattern=re.compile('佟丽娅')   #compile编写  match比赛
result=pattern.match(msg)    #结果为None,没有匹配时返回空  match是从头开始匹配,如果头部没有,就返回空
print(result)

msg='佟丽娅heiehieieheihe'
pattern=re.compile('佟丽娅')   #compile编写  match比赛
result=pattern.match(msg)    #结果为<_sre.SRE_Match object; span=(0, 3), match='佟丽娅'>   match是从头开始匹配,匹配到了
print(result)

print('-----------推荐使用下边方式-------------------')
s='杰伦娜扎热巴代斯佟丽娅'
result=re.match('娜扎',s)   #使用正则re模块的match方法,从开头进行匹配,如果匹配不成功则返回None
print(result)

result=re.search('娜扎',s)  #使用正则re模块的search方法,从头开始匹配一直到尾部,直到找到
print(result)
print(result.span())   #使用对象.span()  调查匹配的字符串的具体位置 返回位置 (2, 4)
print(result.group())  #使用对象.group()  提取你要匹配的内容
print(result.groups())    #使用对象.groups()

#以上只是正则匹配固定字符串,效果跟find差不多 ,正则表达式真正的使用环境是不固定字符串的匹配

结果为
<_sre.SRE_Match object; span=(0, 3), match='佟丽娅'>
-----------推荐使用下边方式-------------------
None
<_sre.SRE_Match object; span=(2, 4), match='娜扎'>
(2, 4)
娜扎
()

2.正则表达式之findall

// 
#现有一串字符串,要你提取出第一位任意字母,第二位任意数字,第三位任意字母
#如 a2b d5m c9k   原字符串为‘abs23bxe3tsd8gsd872gsdf83g9sa’
import re
msg='abs23bxe3tsd8gsd872gsdf83g9sa'
result=re.search('',msg)
print(result.group())
print('------------------')

msg='abs23bxe3tsd8gsd872gsdf83g9sa'     ##现有一串字符串,要你提取出第一位任意字母,第二位任意数字,第三位任意字母
                                        #如 a2b d5m c9k   原字符串为‘abs23bxe3tsd8gsd872gsdf83g9sa’
result=re.search('[a-z][0-9][a-z]',msg)  #[]表示的是一个范围
print(result)
print(result.group())

msg='5551235233574395'
result=re.search('[123]',msg)  #[]中的123 任意取一个值匹配原字符串
print(result)
print(result.group())

print('--------------以下为查询所有符合条件的findall---------------------')
#re.search 只寻找到一个符合条件的后,他就不再往下寻找
#re.findall  寻找所有符合条件的,推荐使用
msg='abs23bxe3tsd8gsd872gsdf83g9sa'
result=re.findall('[a-z][0-9][a-z]',msg)  #findall匹配整个字符串,找到一个继续向下找一直到字符串结尾
print(result)
msg='abs23bxe3tsd8gsd872gsdf831234123g9sa'
result=re.findall('[a-z][0-9]+[a-z]',msg)  #用+  贪婪匹配,将前面的模式匹配1次或多次 >=1
print(result)

result=re.findall('[a-z][0-9]{1,3}[a-z]',msg)  #{m,n}  用于将前面的模式匹配m次到n次(贪婪模式), 即最小匹配m次 , 最大匹配n次
print(result)

result=re.findall('[a-z][0-9]?[a-z]',msg)
print(result)

结果为
------------------
<_sre.SRE_Match object; span=(7, 10), match='e3t'>
e3t
<_sre.SRE_Match object; span=(3, 4), match='1'>
1
--------------以下为查询所有符合条件的findall---------------------
['e3t', 'd8g', 'g9s']
['s23b', 'e3t', 'd8g', 'd872g', 'f831234123g']
['s23b', 'e3t', 'd8g', 'd872g', 'g9s']
['ab', 'bx', 'e3t', 'sd', 'gs', 'gs', 'df', 'g9s']
-------------行首和行尾判断------------------

3.正则表达式之高级用法

// 
定义正则验证次数
用*  贪婪匹配,尽可能多的匹配,用于将前面的模式匹配0次或多次 >=0
用+  贪婪匹配,将前面的模式匹配1次或多次    >=1
用?  贪婪匹配,将前面的模式匹配0或1次      0,1
*? +? ?? 即上面三种特殊字符的非贪婪模式,尽可能少匹配
{m} 用于验证将前面的模式匹配m次           =m
{m,} 用于验证将前面的模式匹配m次或者多次   >=m
{m,n}  用于将前面的模式匹配m次到n次(贪婪模式), 即最小匹配m次 , 最大匹配n次
{m,n}?  即上面{m,n}的非贪婪版本

现在我又有需求了 字母+数字+字母  字母+数字+数字+字母 字母+数字数字数字+字母
// 
#qq号码的验证
#5-11位 , 且0不能作为开头 全部是数字
qq='421432454'
result=re.match('[1-9][0-9]{4,11}',qq)  #match 从头开始检查,首字母不为05-11位并且全为数字
print(result)

#^ 表示开头 $ 表示结尾  常用于re.函数('^[]  $')中,强行将被比较对象qq 放入正则表达式中比对,规定好了匹配的长度,一旦少于或者多,就None
result=re.match('^[1-9][0-9]{4}$',qq)  #全字符串的完全匹配 全匹配常配合 ^ $ {m} 三个共同使用
print(result)

结果为
<_sre.SRE_Match object; span=(0, 9), match='421432454'>
None

3.1 例子二

//
import re
#用户名可以是字母或者数字,但不能是数字开头,用户名长度必须6位以上[0-9a-zA-Z]
username='001admin'
result=re.match('[a-zA-Z][0-9a-zA-Z]{5,}',username)
print(result)

#带特殊字符的匹配
username='a001admin####$$$%%%%###'
result=re.match('[a-zA-Z][0-9a-zA-Z]{5,}',username)  #不带$  match完全匹配时常与$联合使用  ^反倒不用,search是两个都用
print(result)

username='a001admin####$$$%%%%###'
result=re.match('[a-zA-Z][0-9a-zA-Z]{5,}$',username)  #带上$ 后,强制字符串一直到结尾都必须是[0-9a-zA-Z]
print(result)

username='a001admin####$$$%%%%###'
result=re.search('^[a-zA-Z][0-9a-zA-Z]{5,}$',username)  #一般情况,完全匹配时常用match,但你要用search也行,search完全匹配时需要配合^ $ 使用
print(result)
print('------------------------------------------------------')

结果为
None
<_sre.SRE_Match object; span=(0, 9), match='a001admin'>
None
None

3.2 高级用法2

// 
#[0-9a-zA-Z_] 如果觉得这样麻烦,可以使用\w这种代替  []
# \A 表示从字符串的开始处匹配
# \Z 表示从字符串的结束处匹配,如果存在换行,只匹配到换行前的结束字符串
# \b 匹配一个单词边界,也就是指单词和空格间的位置,例如,'py\b'可以匹配"python"中的py,但不能匹配openpyx1中的py
# \B 匹配非单词边界。'py\B'可以匹配'openpyx1'中的py,但不能匹配'python'中的'py'
# \d 匹配任意数字 ,等价于[0-9]
# \D 匹配任意非数字字符,等价于[^\d]
# \s 匹配任意空白字符,等价于[\t\n\r\f]
# \S 匹配任意非空白字符,等价于[^\s]
# \w 匹配任意字母数字及下划线,等价于[a-zA-Z0-9_]
# \W 匹配任意非字母数字及下划线,等价于[^\w]
# \\ 匹配原义的反斜杠\

//
username='a001admin####$$$%%%%###'
result=re.search('[a-zA-Z]\w{5,}',username)  #一般情况,完全匹配时常用match,但你要用search也行,search完全匹配时需要配合^ $ 使用
print(result)

#使用\b 单词边界,常用于搜查文件名   重点!!!
msg='aa.py ab.txt bb.py kk.png uu.py py.txt'
result=re.findall('py\\b',msg)      #\\b本来是有意思的,他不是正则里的\b,所以要\\b原义化\b  ,目前只有\b需要转 要么\\b 要么r\b
print(result)                   #['py', 'py', 'py', 'py'] 4个py,说明他取了单词头部和尾部的py

#原'.'  用于匹配除换行符(\n)外的所有字符
msg='aa.py ab.txt bb.py kk.png uu.py py.txt'
result=re.findall(r'\w+\.py\b',msg)      #\\b本来是有意思的,他不是正则里的\b,所以要\\b原义化\b  ,目前只有\b需要转 要么\\b 要么r\b
print(result)                   #如何处理aa.py中的那个点  \. 或者[.]

msg='aa.py ab.txt bb.py kk.png uu.py py.txt'
result=re.findall(r'\w+[.]py\b',msg)      #\\b本来是有意思的,他不是正则里的\b,所以要\\b原义化\b  ,目前只有\b需要转 要么\\b 要么r\b
print(result)                   #如何处理aa.py中的那个点  \. 或者[.]

结果为
<_sre.SRE_Match object; span=(0, 9), match='a001admin'>
['py', 'py', 'py', 'py']
['aa.py', 'bb.py', 'uu.py']
['aa.py', 'bb.py', 'uu.py']
// 
# 手机号正则
phone=''
re.match('1[3578]\d{9}',phone)

4.正则实例之匹配数字0-100

// 
# 分组
#匹配数字0-100
import re
n='0'
result=re.match('[1-9]?\d',n)  #?问号表示[1-9]可出现也可不出现,不出现那就是一位数字了,出现了就是两位数
print(result)                   #<_sre.SRE_Match object; span=(0, 1), match='0'>

n='09'
result=re.match('[1-9]?\d',n)  #因为第一位是0,所以[1-9]? 不生效,只生效了\d,所以他只匹配了1print(result)                   #<_sre.SRE_Match object; span=(0, 1), match='0'>

n='100'
result=re.match('[1-9]?\d',n)  #匹配100时,[1-9]?生效,\d生效,但是没有第三位了 所以结果为
print(result)                   #<_sre.SRE_Match object; span=(0, 2), match='10'>

#从上边发现,可以解决一位数和两位数的情况,但是如果多一位就不行了,这时候用到 | 分组
n='100'
result=re.match(r'[1-9]?\d?$|100$',n)  #
print(result)

结果为
<_sre.SRE_Match object; span=(0, 1), match='0'>
<_sre.SRE_Match object; span=(0, 1), match='0'>
<_sre.SRE_Match object; span=(0, 2), match='10'>
<_sre.SRE_Match object; span=(0, 3), match='100'>

4.1 提取手机号的区号和手机号 验证邮箱等

//
#验证输入的邮箱 163 126 qq
email='727192970@163.com'
result=re.match(r'[1-9a-zA-Z]\w*[@](163|126|qq)[.](com|cn)$',email)  #()表示一个整体的或者 , []表示单个字母的或者
print(result)                                          #(word|word|word)表示是一个单词随机选,[abc]表示一个字母而不是一个单词
print(result.group())

#不是以4,7 结尾的手机号码(11)
phone='15981930391'
result=re.match(r'[1][5678]\d{8}(|0-3|5|6|8|9)$',phone) #这样写是错误的(0-3|5)这种写法不对
print(result)

phone='15981930391'
result=re.match(r'[1][5678]\d{8}[0-35689]$',phone) #应该这样写
print(result)

结果为
<_sre.SRE_Match object; span=(0, 17), match='727192970@163.com'>
727192970@163.com
None
<_sre.SRE_Match object; span=(0, 11), match='15981930391'>

4.2 爬虫实例1

// 
#爬虫实例
#将手机号的区号和手机号分别提取出来
phone='010-15981930391'
#区号有可能是三位,也可能是四位
result=re.match(r'(\d{3}\d?)-(\d{11})$',phone)  #也可以r'(\d{3}|\d{4})' 将?改为 |
print(result)
#分别提取
print(result.group())
print(result.group(1))  #group()里可以传参,但是前提是正则里必须分组,r'() ()'
print(result.group(2))  #group(1)表示第一组,group(2)表示第二组

结果为
<_sre.SRE_Match object; span=(0, 15), match='010-15981930391'>
010-15981930391
010
15981930391

4.3 网页爬虫 重点

//
#爬虫时,爬到了一个标签,提取标签里的内容
msg='<html>abc</html>'
msg1='<h1>hello</h1>'
result=re.match(r'<\w+>(.+)<(/)\w+>$',msg)
print(result)
print(result.group(1))
print(result.group(2))  #group() 传入参后可以取到()中任意字符

msg='<html><h1>abc</h1>'
result=re.match(r'<\w+>(.+)<(/)\w+>$',msg)
print(result)
print(result.group(1))  #结果为<h1>abc,显然不符合我们要求,因为左边有右边却没有 这就需要用number

#number  \number 引用第number组的数据    难点!!!
#分组常用于 要保持前后一致的情况,如网页爬虫
msg='<h1>hello</h1>'
result=re.match(r'<([0-9a-zA-Z]+)>(.+)</(\1)>$',msg1)  #\1 表示引用左边匹配的第一号,如果不一致,就None
print(result)
print(result.group(1))
print(result.group(2))
print(result.group(3))

msg='<html><h1>abc</h1></html>'  #标签格式开闭要对应 现在我们要检查标签格式是否对应,用到number技术,还有我们要提取出标签中心的内容
result=re.match(r"<(\w+)><(\w+)>(.+)</(\2)></\1>", msg)  #\1 引用第一个()内的内容, \2 引用第二个()内的内容 ,\1\2的作用是与前边括号内的内容进行比对,如果不一致,就返回Noen,常用来检查html中标签是否开闭正确
print(result)
print(result.group(1))
print(result.group(2))
print(result.group(3))
print(result.group(4))

print('---------------最后实例---------------')
#分组起名的方式
# (?P<名字>正则) 前边?P表示要起个名字,方便\1对照 \1也会转变为(?P=名字)
msg='<html><h1>abc</h1></html>'
result=re.match(r'<(?P<name1>.+)><(?P<name2>\w+)>(.+)</(?P=name2)></\1>',msg)
print(result)
print(result.group('name1'))


结果为
<_sre.SRE_Match object; span=(0, 16), match='<html>abc</html>'>
abc
/
<_sre.SRE_Match object; span=(0, 18), match='<html><h1>abc</h1>'>
<h1>abc
<_sre.SRE_Match object; span=(0, 14), match='<h1>hello</h1>'>
h1
hello
h1
<_sre.SRE_Match object; span=(0, 25), match='<html><h1>abc</h1></html>'>
html
h1
abc
h1
---------------最后实例---------------
<_sre.SRE_Match object; span=(0, 25), match='<html><h1>abc</h1></html>'>
html

5.贪婪匹配与非贪婪 ?

//
#python里数量词默认是贪婪的(在少数语言里也可能默认是非贪婪),总是尝试匹配更多的字符
import re

#默认是贪婪的
msg='abc123abc'
result=re.match(r'abc(\d+)',msg)   #结果为'abc123'
print(result)

#如果想变成非贪婪,就加?
msg='abc123abc'
result=re.match(r'abc(\d+?)',msg)   #结果为'abc1'
print(result)

结果为
<_sre.SRE_Match object; span=(0, 6), match='abc123'>
<_sre.SRE_Match object; span=(0, 4), match='abc1'>

5.1 爬虫

// 
path='<img class="BDE_Image" src="http://tiebapic.baidu.com/forum/w%3D580/sign=d2c23b50319759ee4a5060c382fa434e/a5ba08f790529822a836669ec0ca7bcb0b46d484.jpg" ' \
     'size="352811" changedsize="true" width="560" height="746">'
#寻找这个图片,看src的那个内容 http://tiebapic.baidu.com/forum/w%3D580/sign=d2c23b50319759ee4a5060c382fa434e/a5ba08f790529822a836669ec0ca7bcb0b46d484.jpg
result=re.match(r'<img class="BDE_Image" src="(.+)"',path)
print(result)
print(result.group())  #<img class="BDE_Image" src="http://tiebapic.baidu.com/forum/w%3D580/sign=d2c23b50319759ee4a5060c382fa434e/a5ba08f790529822a836669ec0ca7bcb0b46d484.jpg" size="352811" changedsize="true" width="560" height="746"
print(result.group(1))
print(result.span())

#加上? 的非贪婪模式,如果有一个满足条件就停止,所以.+? 只会匹配一位  而贪婪模式.+ 一直往后匹配
result=re.match(r'<img class="BDE_Image" src="(.+?)',path)   #结果为<_sre.SRE_Match object; span=(0, 29), match='<img class="BDE_Image" src="h'>
print(result)
result=re.match(r'<img class="BDE_Image" src="(.+?)\.jpg"',path)    #因为后边有限制条件\.jpg,所以他本来只会匹配一位他也会继续往后匹配
print(result.group())
print(result.group(1))
print(result.span())

import requests
image_path=result.group(1)
response=requests.get(image_path)
with open('aa.jpg','wb') as wstream:
          wstream.write(response.content)


结果为
<_sre.SRE_Match object; span=(0, 209), match='<img class="BDE_Image" src="http://tiebapic.baidu>
<img class="BDE_Image" src="http://tiebapic.baidu.com/forum/w%3D580/sign=d2c23b50319759ee4a5060c382fa434e/a5ba08f790529822a836669ec0ca7bcb0b46d484.jpg" size="352811" changedsize="true" width="560" height="746"
http://tiebapic.baidu.com/forum/w%3D580/sign=d2c23b50319759ee4a5060c382fa434e/a5ba08f790529822a836669ec0ca7bcb0b46d484.jpg" size="352811" changedsize="true" width="560" height="746
(0, 209)
<_sre.SRE_Match object; span=(0, 29), match='<img class="BDE_Image" src="h'>
<img class="BDE_Image" src="http://tiebapic.baidu.com/forum/w%3D580/sign=d2c23b50319759ee4a5060c382fa434e/a5ba08f790529822a836669ec0ca7bcb0b46d484.jpg"
http://tiebapic.baidu.com/forum/w%3D580/sign=d2c23b50319759ee4a5060c382fa434e/a5ba08f790529822a836669ec0ca7bcb0b46d484
(0, 151)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值