第十六天


正则表达式
第一部分
正则表达式:对指定的字符串跟模式(模板)之间进行的模式匹配,
可以获得匹配结果,也可以获得匹配之后的内容。

模式(正则表达式):可以是普通的字符,也可以是特殊的字符。

# 模式:普通字符串:安全按照字符串本身的内容进行匹配。给定的内容是不是 包含了模板的内容
# "addjdjdsfjsa"这个字符串中跟给定一个模式"add"是否匹配
# "abc" in "addjdjfakldjf"
# 在python中 我们使用re模块
import re
# re.search方法
# 第一个参数:模式字符串
# 第二个参数:是传入的字符串,待搜索的字符串。
# 第三个参数:标志
# 返回值是正则表达式对象

r=re.search("add","addhjfkshjkfdsa")
if r:
print("匹配成功")
print(r.group())
else:
print("匹配不成功")
s="abc"

# 模式是特殊字符的时候,正则表达式才发挥作用
# 如:字符串是不是一个电话号码

# 正则表达式对象可以返回匹配的内容
# r.group()

# 正则表达式的特殊字符
一、 字符相关
1. . 默认模式下,匹配除了\n以外的所有【单个】字符
# 如果第三参数模式是S模式(DOTALL),那么会匹配所有的字符
# r=re.search("a.b","dkkjhahioib")
r=re.search("a.b","dkkjha\nb",re.DOTALL)
if r:
print(r.group())
else:
print("不匹配")

2. [] 中括号,匹配在中括号内的任意一个字符,在中括号中,可以是多个字符,也可以是一个区间
# 单个多个字符[x9k]
r=re.search("a[abcde]b","kipoa*bki;ks;ld")
if r:
print(r.group())

# 区间[a-z]
r=re.search("a[a-z]b","kipoa*bki;ks;ld")
if r:
print(r.group())
# 如果希望模板中匹配-和[],特殊字符,必须使用\转义,或者是在边缘
r=re.search("a[a\-z]b","bkiiosa-b")
if r:
print(r.group())

r=re.search("a[-z]b","bkiiosa-b")
if r:
print(r.group())
r=re.search("a[-z\]a]b","bkiiosa-b")
if r:
print(r.group())
r=re.search("a[]-z]b","bkiiosa-b")
if r:
print(r.group())
3. ^匹配不在[]内的任何一个字符,[]取反,注意,使用的时候,只能临近[^a-z]用
r=re.search("a[^0-9]","bkiiosa-b")
if r:
print(r.group())

4. \d代表是数字和特殊的字符(希腊字母),一般来说不是要求很严格,可以使用\d代表0-9
r=re.search("a\db","bkiiosa0b")
if r:
print(r.group())
# python\也是转义,建议在双引号前面加r

5. \D代表跟\d取反
r=re.search("a\Db","bkiiosa0b")
if r:
print(r.group())
6. \s代表匹配空白符 \r\n\v
# r=re.search("a\sb","bkiiosa b")
r=re.search("a\sb","bkiiosa\nb")
if r:
print(r.group())
7. \S代表跟\s取反
r=re.search("a\Sb","bkiiosa5b")
if r:
print(r.group())

8. \w代表字符[a-zA-Z0-9_]
r=re.search("a\wb","bkiiosa_b")
if r:
print(r.group())

9. \W代表\w取反
r=re.search("a\Wb","bkiiosa-b")
if r:
print(r.group())

10. (重要)\转义字符

二、 次数相关
1. * 匹配前面的字符0次或者多次。不能单独使用。
# 会从0个开始,一直匹配,匹配到不匹配位置
r=re.search("a*","qqqqqa")
r=re.search("a*","qqqqqqq")
r=re.search("ba*","baaaaaauuu")
r=re.search("ba*","ba")
r=re.search("ba*","b")
r=re.search(r"ba*","44444baaaaauuu")
if r:
print(r.group())
else:
print("不匹配")
# 贪婪式匹配

2. + 代表1或者多次
r=re.search(r"ba+","44444444baaaaaaaaauuuu")
if r:
print(r.group())
else:
print("不匹配")

3. ? 代表0或者1次 # 代表的是最少匹配次数
r=re.search(r"ba?","44444444baaaaaaaaauuuu")
if r:
print(r.group())
else:
print("不匹配")

4. {m} 精确匹配m次
# r=re.search(r"ba{4}","44444444baaauuuu")
r=re.search(r"ba{4}","44444444baaaaaauuuu")
if r:
print(r.group())
else:
print("不匹配")

5. {m,} 至少匹配m次
# r=re.search(r"ba{4}","44444444baaaauuuu")
r=re.search(r"ba{4,}","44444444baaaaauuuu")
if r:
print(r.group())
else:
print("不匹配")

6. {,n} 匹配前面的字符最多n次
# r=re.search(r"ab{,4}","a")
r=re.search(r"ab{,4}","abbbbbb")
if r:
print(r.group())
else:
print("不匹配")

7. {m,n} 匹配m到n次
r=re.search(r"ab{3,5}","abbbbbbb")
if r:
print(r.group())
else:
print("不匹配")

# * 0或者多次 , 使用{m,n} {0,}和*是一样的效果

X? X代表除了精确匹配{m}以外的其他次数字符。加?代表将原来的贪婪匹配转化成非贪婪模式
# r=re.search(r"ba*?","baaaaaaa")
r=re.search(r"ba+?","baaaaaaa")
if r:
print(r.group())
else:
print("不匹配")

# 练习
# 匹配任意三个字符
r=re.search(".{3}","abcd")
if r:
print(r.group())
else:
print("不匹配")
# 匹配任意1个乃至更多的字符
r=re.search(".+","abcd")
r=re.search(".+","")
if r:
print(r.group())
else:
print("不匹配")

三、 边界相关
1. ^:匹配字符串的开头
# 默认是单行模式(第一行),如果希望支持多行,需要修改标注MUTLINE
# r=re.search(r"^张","张三丰")
# r=re.search(r"^张","三丰\n张什么",re.MULTILINE)
r=re.search(r"^张","张三丰\n张什么",re.MULTILINE)
if r:
print(r.group())
else:
print("不匹配")

2. $匹配的字符串的结尾,分为默认(单行模式),同M设置多行模式
r=re.search(r"\.com$","http://www.baidu.com\nhttp://www.souhu.com",re.MULTILINE)
if r:
print(r.group())
else:
print("不匹配")
r=re.search(r"\w+\.com$","http://www.baidu.com")
if r:
print(r.group())
else:
print("不匹配")

3. \A 仅匹配字符串的开头,默认跟^一样,但是永远是单行模式,re.MULTILINE无效。
r=re.search(r"\A张","三丰\n张什么",re.MULTILINE)
if r:
print(r.group())
else:
print("不匹配")
4. \Z 匹配字符串的结尾,默认跟$一样,但是永远是单行模式

5. \b 匹配单词的边界。 unicode字符,\w匹配的内容都可以称为是单词
# r=re.search(r"\bcd","cd")
# r=re.search(r"\bcd","88#$$^cd")
r=re.search(r"\bcd","88#$$1cd")
r=re.search(r"\bcd","acd")
if r:
print(r.group())
else:
print("不匹配")

6. \B 按照\b取反
r=re.search(r"\Bcd","acd",)
if r:
print(r.group())
else:
print("不匹配")

四、组相关
1. () 对()里面的字符进行分组,分组之后,匹配的内容可以单独提取
# () : 对括号内的内容进行整体操作,group(index)括号里指的是索引
r=re.search(r"c(ab)+","cabababab",)
if r:
print(r.group())
print(r.group(1)) # 1 是第一个括号
else:
print("不匹配")

# <b>一些内容<\b>
r=re.search(r"<b>(.*)<\b>","<b>一些内容<\b>",)
if r:
print(r.group())
print(r.group(1))
else:
print("不匹配")

# 010-12345678
r=re.search(r"[0-9]{3,4}-[0-9]{7-8}","010-12345678",)
if r:
print(r.group())
print(r.group(1))
else:
print("不匹配")

2. \number 用来指定组序号,序号从1开始,第几个括号,匹配第几个括号的内容
# <b>..<title>这是标题....</title>... <\b>
# r=re.search(r"<([a-zA-Z]+)>(.*)<[a-zA-Z]+>","<title>一些内容<\b>",)
# 应用的时候,可以跟()一起使用,达到前后标签,内容一致的效果。
r=re.search(r"<([a-zA-Z]+)>(.*)</\1>","<title>一些内容<title>",)
if r:
print(r.group())
print(r.group(1))
print(r.group(2))
else:
print("不匹配")

3. (?: 表达式) 匹配()中的字符,但是不能进行分组,不能使用number (group(number))和number
# 只能划分整体
r=re.search(r"abc(?:def)+","abcdef")
if r:
print(r.group())
print(r.group(1))
print(r.group(2))
else:
print("不匹配")

4. (?P<name>表达式):对()内容分组,并且给()命名name,多个组之间的名称不能重复
# r=re.search(r"<(?P<tag>[a-zA-Z]+)>(.*)</\1>","<title>一些内容<title>",)
r=re.search(r"<(?P<tag>[a-zA-Z]+)>(.*)</(?P=tag)>","<title>一些内容<title>",)
if r:
print(r.group())
print(r.group(1))
print(r.group(2))
else:
print("不匹配")

5. | 用来连接两个并列的模式字符串。匹配其中一个就可以
# 注意,是划分大区域,分两片
# [abcd]
# r=re.search(r"abc|def","abc",)
# r=re.search(r"abc|def","abd",)
# 如果希望划分小片区域,可以使用()分组
r=re.search(r"ab(c|d)ef","abdef",)
if r:
print(r.group())

else:
print("不匹配")
"""
.com .net .edu
\.(com|edu|net)
"""

控制标记
# IGNORECASE:匹配的时候忽略大小写
# MULTILINE:匹配多行
# DOTALL:匹配所有包括\n
r=re.search(r"abc","ABC",re.IGNORECASE)
if r:
print(r.group())

else:
print("不匹配")

第二部分
"""
相关属性和方法
"""
import re
1. compile 生成一个正则表达式对象,之后可以调用对象下的方法,进行跟其他字符的匹配
# re.compile(模式,标记),
reobject=re.compile("abc+")
m=reobject.search("abcccc")
reobject.search("abccccc",0,3)
if m:
print(m.group())
# search 几乎跟re模块下的search作用一样。
# 出现循环,或者重复使用的时候,可以使用正则表达式对象
# 需求:在大量的文件中匹配电话号码

for item in ["文件列表,可迭代对象,路径"]:
with open(item) as f:
f_content=f.read()
# re.search("模板",f_content)

for item in ["文件列表,可迭代对象,路径"]:
with open(item) as f:
f_content=f.read()
# re.search("模板",f_content)
reobject.search(f_content)
# 正则表达式对象下的search跟re模块下的search相比:
# 1. 如果出现重复使用,可以使用正则表达式下面的search
# 2. 正则表达式下的search有指定区间的功能
# 如果非想re模块下的search,可以使用切片指定区间。
re.search("abc","absdjlksjlfj"[0:3])

2. re.search()

3. re.match() 跟search功能基本类似,但是只能从头部进行查询。
# m=re.search("abc","xabc")
m=re.match("abc","xabc")
if m:
print(m.group())
else:
print("不匹配")

4. findall() 返回所有匹配的内容,以列表的形式
li=re.findall("[0-9]","xab2cj23jjfd093ju8d0")
print(li)
# 如果表达式中()。那么findall返回的是()内的值
c="<div>我是一个兵</div><div>来自老百姓</div><div>...</div>"
mode="<div>(.*?)</div>"
li=re.findall(mode,c)
print(li)

5. finditer() 跟findall类似,返回的是迭代器
c="<div>我是一个兵</div><div>来自老百姓</div><div>...</div>"
mode="<div>(.*?)</div>"
iter=re.findall(mode,c)
print(iter)
for item in iter:
print(item.group())

6. split() 分隔
s="a bdc d d a"
print(s.split(" "))

li=re.split(" +",s)
print(li)

7. sub() 替换 在str中有replace,返回新的字符串
# 第一个参数:替换的模式(要替换的内容)
# 第二个参数:替换后的内容
# 第三个参数:待搜索的字符串
# 第四个参数:最大的替换次数
# 第五个次数:控制标记
str_new=re.sub(" +"," ","a dd s s g s a a ")
print(str_new)

第三部分
"""
正则表达式对象
"""
# 正则匹配成功之后,会返回一个Match对象
import re
m=re.search("ab\d","a123123sabvasd"[3:15])
if m:
# 待匹配文本
print(m.string)
# 返回正则表达式的模式
print(m.re)
# 返回字符串搜索的起始位置和结束位置
print(m.pos)
print(m.endpos)
# 返回匹配后的字符串
print(m.group())

import re
m=re.search("(a+)-(b+)","bbbbaaaa-bbbbb")
if m:
print(m.group())
# 返回一个元组类型,元组中元素是所有分组匹配的结果
print(m.groups())
# 匹配内容在搜索字符串中开始的位置(从什么时候开始匹配)
print(m.start())
# 匹配内容在搜索字符串中结束的位置(结束位置不包含在内)
print(m.end())
# start和end的元组
print(m.span())

# 1. 获取<tr></tr>标签之间的内容
htmltext="""
<tr>
>th>AA</th><th>BB</th>
</tr>
<tr>
<td>AA内容</td><td>BB内容</td>
</tr>
<tr>
<th>CC</th><th>DD</th>
</tr>
<tr>
<td>CC内容</td><td>DD内容</td>
</tr>
"""
re_str="<tr>(.*?)</tr>"
m_tr=re.findall(re_str,htmltext,re.DOTALL)
print(m_tr)
for line in m_tr:
re_th="<th>(.*?)</th>"
m_th=re.findall(re_th,line,re.DOTALL)
print(m_th)
for mm in m_th:
print(mm)

re_td="<td>(.*?)</th>"
m_td=re.findall(re_td,line,re.DOTALL)
for nn in m_td:
print(nn)
# 2.
htmltext2="""
<a href="https://www.baidu.com" titlt="浙江省">浙江省新闻</a>
<a title="贵州省" href="https://www.baidu1.com">贵州省新闻</a>
<a href="https://www.baidu2.com" title="辽宁省">辽宁省新闻</a>
"""
"""
1. 获取<a href>浙江省新闻</a>之间内容
2. 整个a标签的内容
3. 只获得url的内容
"""
# 1.
res1="<a .*?>(.*?)</a>"
mm=re.findall(res1,htmltext2,re.DOTALL|re.IGNORECASE|re.MULTILINE)
# print(mm)
for i in mm:
print(i)

# 2.
res2="<a .*?>.*?</a>"
mm2=re.findall(res2,htmltext2,re.DOTALL|re.IGNORECASE|re.MULTILINE)
for i in mm2:
print(i)

# 3.
res3=r"<a.*?href=\"(.*?)\".*?</a>"
mm3=re.findall(res3,htmltext2,re.DOTALL|re.IGNORECASE|re.MULTILINE)
print(mm3)
for i in mm3:
print(i)
 
posted on 2018-06-04 09:07  不虚此行ztx  阅读(97)  评论(0编辑  收藏  举报