Python零基础速成班-第13讲-Python正则表达式Regex

Python零基础速成班-第13讲-Python正则表达式Regex

学习目标

  1. 正则表达式
  2. 课后作业(4必做)

友情提示:将下文中代码拷贝到JupyterNotebook中直接执行即可,部分代码需要连续执行。

1、正则表达式Regex

  1. 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。Python 自1.5版本起增加了 re 模块,re 模块使Python语言拥有全部的正则表达式功能。
  2. 正则表达式可以帮我们轻松验证电话号码、电子邮件、密码强度、输入长度等各种类型的格式是否正确,进而实现数据校验的功能。
  3. 下表为Python re 模块正则表达式常用规则:(后面将会使用)
正则表达式 描述 正则表达式 描述
. 匹配任意字符,除了换行符 {n,m} 重复n到m次
\w 匹配字母数字及下划线 \W 匹配非字母数字及下划线
\s 匹配任意空白字符 \S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9] \D 匹配任意非数字
\b 匹配一个单词边界,也就是指单词和空格间的位置 \B 匹配非单词边界
^ 匹配字符串的开头 [^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符
$ 匹配字符串的末尾 [0-9] 匹配任何数字。类似于 [0123456789]
* 重复零次或更多次 [a-z] 匹配任何小写字母
+ 重复一次或更多次 [A-Z] 匹配任何大写字母
? 重复零次或一次 [a-zA-Z0-9] 匹配任何字母及数字
{n} 重复n次 [^aeiou] 除了aeiou字母以外的所有字符
{n,} 重复n次或更多次 [^0-9] 匹配除了数字外的字符

1.1 re.match起始匹配函数

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回 none。
函数语法:

re.match(pattern, string, flags=0)

参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等
flags正则表达式修饰符 - 可选标志
修饰符 描述
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
匹配成功 re.match 方法返回一个匹配的对象,否则返回 None。

如下例,在起始位置匹配成功,返回匹配对象。

import re
result = re.match(r'www','www.baidu.com')
print(result)

不在起始位置匹配,匹配失败,返回None

import re
result = re.match(r'com','www.baidu.com')
print(result)
None

我们可以使用 group(num) 或 groups() 匹配对象函数来获取匹配表达式。

匹配对象方法 描述
group(默认num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,它将返回一个所对应值的元组
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号
import re
string='Cats are smarter than dogs'
result = re.match(r'(.*) are (.*?) .*',string)
print(result)
print(result.group())
print(result.group(1))
print(result.group(2))
print(result.groups())

Cats are smarter than dogs
Cats
smarter
('Cats', 'smarter')

1.2 re.search整体匹配函数

re.search 扫描整个字符串并返回第一个成功的匹配。函数语法:

re.search(pattern, string, flags=0)

参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等
匹配成功re.search方法返回一个匹配的对象,否则返回None。

如下例,匹配一次或更多次数字。

import re
result = re.search(r'\d+','阅读次数 9999次')
print(result)
print(result != None)

True

同样我们也可以使用 group(num) 或 groups() 匹配对象函数来获取匹配表达式。

匹配对象方法 描述
group(默认num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,它将返回一个所对应值的元组
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号
import re
mo = re.search(r'(\d\d\d)-(\d\d\d-\d\d\d\d)','My number is 415-555-4242.')
print(mo)
print(mo.group())
print(mo.group(1))
print(mo.group(2))
print(mo.groups())

415-555-4242
415
555-4242
('415', '555-4242')

1.3 re.match与re.search的区别

re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;
而re.search匹配整个字符串,直到找到一个匹配。
如下例:

import re
string = "Cats are smarter than dogs"
#match
matchObj = re.match( r'dogs', string, re.M|re.I)
if matchObj:
    print("match --> matchObj.group() : ", matchObj.group())
else:
    print("No match!!")
#search
matchObj = re.search( r'dogs', string, re.M|re.I)
if matchObj:
    print("match --> matchObj.group() : ", matchObj.group())
else:
    print("No match!!")
No match!!
match --> matchObj.group() :  dogs

1.4 re.compile 预编译函数

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。函数语法:

re.compile(pattern[, flags])

  • pattern : 一个字符串形式的正则表达式
  • flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,如re.I 忽略大小写、re.M 多行模式、re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境等,详见上述1.1《flags正则表达式修饰符 - 可选标志》表。
import re
Regex = re.compile(r'\baaa')
result = Regex.search('aaaaaabbb')
print(result)

import re
Regex = re.compile(r'\(\d\)')
test = Regex.search('sss (5) 2222')
print(test.group())
(5)
1.4.1 pipe 管道

"|"字符称为管道。您可以在任何需要匹配多个表达式之一的地方使用它。
第一次出现的匹配文本将作为匹配对象返回。

import re
heroRegex = re.compile (r'Batman|Tina Fey')
mo1 = heroRegex.search('Batman and Tina Fey')
print("1:"+mo1.group())# first occurrence is Batman

mo2 = heroRegex.search('Tina Fey and Batman')
print("2:"+mo2.group())# first occurrence is Tina Fey
1:Batman
2:Tina Fey
import re
batRegex = re.compile(r'Bat(man|mobile|copter|bat)')
mo = batRegex.search('Batmobile lost a wheel')
print(mo)
print("2:"+mo.group(0))#Bat(mobile...
print("3:"+mo.group(1))#(mobile...)

2:Batmobile
3:mobile
1.4.2 ? * + 的应用
  • “?” 表示重复0次或1次,即可有可无,满足最低条件
  • “*” 表示重复0次或更多次
  • “+” 表示重复1次或更多次
import re
batRegex = re.compile(r'Bat(wo)?man')
mo1 = batRegex.search('The Adventures of Batman')#无 wo
print(mo1.group())

mo2 = batRegex.search('The Adventures of Batwoman')#有 wo
print(mo2.group())
Batman
Batwoman
import re
batRegex = re.compile(r'Bat(wo)*man')
mo1 = batRegex.search('The Adventures of Batman')#无或者更多次
mo1.group()
'Batman'
import re
batRegex = re.compile(r'Bat(wo)+man')
mo1 = batRegex.search('The Adventures of Batwoman')#1次
print(mo1.group())

mo2 = batRegex.search('The Adventures of Batwowowowoman')#多次
print(mo2.group())

mo3 = batRegex.search('The Adventures of Batman')
print(mo3 == None)
Batwoman
Batwowowowoman
True
1.4.3 {m,n} 的应用
  • {m} 表示重复m次
  • {m,n} 表示重复m到n次,如果超过n次,则选择贪婪模式,即重复n次
  • {m,n}? 表示重复m到n次,且满足最低条件,即重复m次
import re
haRegex = re.compile(r'(Ha){3}')
mo1 = haRegex.search('HaHaHatttttt')
mo1.group()
'HaHaHa'

贪婪模式

import re
haRegex = re.compile(r'(Ha){3,6}')
mo1 = haRegex.search('HaHaHaHaHaHaHaHaHaHa')#贪婪模式,即选择6次
mo1.group()
'HaHaHaHaHaHa'

满足最低条件

import re
greedyHaRegex = re.compile(r'(Ha){3,5}')
mo1 = greedyHaRegex.search('HaHaHaHaHaHaHa')#贪婪模式,即选择5次
print(mo1.group())

nongreedyHaRegex = re.compile(r'(Ha){3,5}?')#满足最低条件,即选择3次
mo2 = nongreedyHaRegex.search('HaHaHaHaHa')
print(mo2.group())
HaHaHaHaHa
HaHaHa

1.5 findall 匹配所有字符串函数

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。
即match 和 search 是匹配一次 而findall 匹配所有。findall函数语法为:

findall(string[, pos[, endpos]])
参数:

  1. string : 待匹配的字符串。
  2. pos : 可选参数,指定字符串的起始位置,默认为 0。
  3. endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。

无分组情况

import re 
phoneNumRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d') #无分组情况
phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000')
['415-555-9999', '212-555-0000']

有分组情况,返回tuple元组

import re 
phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)') #有分组情况
phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000')#返回一个tuple
[('415', '555', '9999'), ('212', '555', '0000')]

指定开始位置和结束位置

import re
numRegex = re.compile(r'\d+')#查找数字
numRegex.findall("6baidu888google12345",0,17)#指定0到17的位置种查询
['6', '888', '12']

[ ]表示匹配中括号内相应内容,如[0-9]即匹配所有数字,[a-z]即匹配所有小写字母,[a-zA-Z0-9]即匹配所有数字字母,[^0-9]即匹配所有非数字

import re
vowelRegex = re.compile(r'ba|[aeiouAEIOU]')#匹配元音
vowelRegex.findall('RoboCop eats baby fOOd.')
['o', 'o', 'o', 'e', 'a', 'ba', 'O', 'O']
import re
vowelRegex = re.compile(r'[^aeiouAEIOU]')#匹配非元音
vowelRegex.findall('RoboCop eats baby fOOd.')
['R', 'b', 'C', 'p', ' ', 't', 's', ' ', 'b', 'b', 'y', ' ', 'f', 'd', '.']
import re
vowelRegex = re.compile(r'[0-5.]')#这里匹配的是"0-5以及."
vowelRegex.findall('123450. BABY FOOD.')
['1', '2', '3', '4', '5', '0', '.', '.']
import re
atRegex = re.compile(r'.at')#这里的"."代表匹配任意字符
atRegex.findall('The cat in the hat ssate on the flat mat.')
['cat', 'hat', 'sat', 'lat', 'mat']

1.6 re.sub 检索和替换函数

Python 的 re 模块提供了re.sub用于替换字符串中的匹配项。函数语法:

re.sub(pattern, repl, string, count=0, flags=0)
参数:

  1. pattern : 正则中的模式字符串。
  2. repl : 替换的字符串,也可为一个函数。
  3. string : 要被查找替换的原始字符串。
  4. count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。

如下例,移除电话号码中的 “-” 字符串,即用 “” 替换 “-”

import re
tel = re.sub(r"\D","","021-8678-0543")
print(tel)
02186780543

re.sub常用来作为某个单词或者姓名的替换,如下例,将Agent后面的姓名替换为新的姓名

import re
namesRegex = re.compile(r'Agent \w+')
namesRegex.sub('Lucifer', 'Agent Alice gave the secret documents to Agent Bob.')
'Lucifer gave the secret documents to Lucifer.'

1.7 一些额外用法的补充

满足最低条件与贪婪模式

import re
nongreedyRegex = re.compile(r'{.*?}')#这里的{}就代表大括号,有?则是满足最低条件即可
mo = nongreedyRegex.search('{To serve man} for dinner}')
print("满足最低条件:",mo.group())

greedyRegex = re.compile(r'<.*>')#没有?号,则是贪婪模式
mo = greedyRegex.search(' for dinner.>')
print("贪婪模式:",mo.group())
满足最低条件: {To serve man}
贪婪模式:  for dinner.>

"."表示任意字符,但不包括换行符\n

import re
noNewlineRegex = re.compile('.*')#这里的"."表示任意字符不包括换行符
noNewlineRegex.search('Serve the public trust.\nProtect the innocent.\nUphold the law.').group()
'Serve the public trust.'

通过修饰符re.S(等同于re.DOTALL),使 . 匹配包括换行在内的所有字符

import re
newlineRegex = re.compile('.*', re.S)#re.S等同于re.DOTALL include all character
newlineRegex.search('Serve the public trust.\nProtect the innocent.\nUphold the law.').group()
'Serve the public trust.\nProtect the innocent.\nUphold the law.'

通过修饰符re.I使匹配大小写不敏感

import re
robocop = re.compile(r'robocop',re.I)
print(robocop.search('RoboCop is part man, part machine, all cop.').group())
print(robocop.search('ROBOCOP protects the innocent.').group())
print(robocop.search('Al, why does your programming book talk about robocop so much?').group())
RoboCop
ROBOCOP
robocop

1.8 先行断言、后行断言,在爬虫中非常有用

exp1是一个句子,exp2是一个句子

先行断言:

  1. exp1(?=exp2) :指查找后面是exp2的exp1
  2. exp1(?!exp2) :指查找后面不是exp2的exp1

后行断言

  1. (?<=exp2)exp1 :指查找前面是exp2的exp1
  2. (?

如下例,查找后面是标签的任意字符串

import re
xianRegex = re.compile(r".+(?=)")
xian = fontRegex.search("阅读数:641")
print(xian.group())
阅读数:641

查找前面是是标签的任意字符串

import re
houRegex = re.compile(r"(?<=)
hou = houRegex.search("阅读数:641")
print(hou.group())
 class="read-count">阅读数:641

2、课后作业,答案在下一讲

1、输入一个IP地址,确认是否是合法的A类IP地址。(A类IP地址 地址范围1.0.0.0到126.255.255.255)

您的代码:

2、写一个函数,它使用正则表达式,确保传入的口令字符串是强口令。强口令的定义是:由数字和字母组成,并且要同时含有数字和字母,且长度要在8-16位之间。

您的代码:

3、这是一个封群发邮件内容,请你用正则表达式将somebody替换成对应姓名,需要替换的姓名列表为 [‘Alice’,‘Tony’,‘Henry’,‘Jack’,‘Yilia’],替换完成后请依次将内容打印出来,邮件内容为:

Hello somebody ,welcome to my home ,I’m waiting for you.

您的代码:

4、将下列不同格式的日期,转换成相同格式yyyy-mm-dd并依次打印出来

输入日期格式有可能如下:
20210601
2021-06-01
2021/06/01
2021/6/1
2021年6月1日
2021年06月01日

您的代码:

3、上一讲Python零基础速成班-第12讲-Python获取网络数据Socket,API接口,网络爬虫Crawler(制作弹幕词云) 课后作业及答案

1、编程实践项目:利用百度智能云API服务制作一个手机号码归属地查询API接口。

  1. 目标要求:输入手机号,查询手机号码归属地信息、包含省市区、运营商、区号等信息。
  2. API接口地址:https://api.oioweb.cn/api/common/teladress
  3. 请求方式:GET/POST
  4. 请求示例GET:https://api.oioweb.cn/api/common/teladress?mobile=13988888888
import requests
import json
def mobilecity(mobile:"手机号")->"输出归属地等信息":
    url = 'https://api.oioweb.cn/api/common/teladress'#API接口地址
    params = {}
    params['mobile'] = mobile
    headers={'Content-Type':'application/json;charset=UTF-8'}
    response = requests.post(url=url,params=params,headers=headers)#使用POST请求
    mobileinfo = json.loads(response.text)
    return mobileinfo["result"]
mobilecity("13988888888")

{‘name’: ‘移动全球通卡’,
‘postCode’: ‘674100’,
‘prov’: ‘云南’,
‘city’: ‘丽江市’,
‘cityCode’: ‘530700’,
‘num’: 1398888,
‘provCode’: ‘530000’,
‘areaCode’: ‘0888’,
‘type’: 1}

2、编程实践项目:利用网络爬虫,爬取文件信息,生成文件的词云图片。

  1. 目标要求:从 http://www.gov.cn/zhengce/2021-02/21/content_5588098.htm 中获取《关于全面推进乡村振兴加快农业农村现代化的意见》网页源码,进行数据整理、分词、生成词云图片并展示。
  2. 提示:
    1. 爬取文件网页源码,转化为utf-8格式。
    2. 寻找文件规律,使用BeautifulSoup查询转化,输出数组,文件信息是以段落标签"p"开头的,不需要去除空格和重复。
    3. 分词,去掉单字符和内容为"\r\n"的单词。
    4. 生成词云图片并展示(图片长度1200,高度800,清晰度3,背景底色白色,字体"msyh.ttc")。
    5. 需要使用requests、BeautifulSoup、jieba、wordcloud、matplotlib包,需要自行安装。
import requests
from bs4 import BeautifulSoup
import jieba
import wordcloud
from matplotlib import pyplot as plt
#爬取网页数据
reponse = requests.get("http://www.gov.cn/zhengce/2021-02/21/content_5588098.htm")
reponse.encoding='utf-8'
#整理
soup = BeautifulSoup(reponse.text,"xml")
result = soup.find_all("p")
text = [c.text for c in result]
#分词
ci = "".join(text)
fenci = list(jieba.cut(ci))
ciyun = [word for word in fenci if len(word)>1 and word not in ["\r\n"]]
#生成词云图片并输出
wc = wordcloud.WordCloud(width=1200, font_path='msyh.ttc',height=800,scale=3,background_color='white')
wc.generate(' '.join(ciyun))
plt.imshow(wc)

Python零基础速成班-第13讲-Python正则表达式Regex_第1张图片

你可能感兴趣的:(Python,python,jupyter,正则表达式,大数据,中文分词)