#!usr/bin/env python
*# -*- coding:utf-8 -*-**
"""
@author:
@file: re_demo.py
@time: 2020/10/25 9:41
"""
import re
"""1、match()"""
*# match()方法尝试从字符串起始位置匹配正则表达式,如果匹配,就返回匹配成功的结果。如果不匹配,就返回None**
"""目标匹配"""
content = """ <h6> 915478897 </h6>
<h6>你收到复核</h6>
<h6>soiufjkghk</h6>
"""
*# ^开头标识 .*通配任意次 \s匹配任意空字符 \d匹配数字 +一次或者多次**
result = re.match("^.*<h6>\s(\d+)\s</h6>", content)
print(result)
print(result.group())
print(result.group(1))
*# 输出下面结果**
*# <re.Match object; span=(0, 23), match=' <h6> 915478897 </h6>'>
*# <h6> 915478897 </h6>
*# 915478897
"""贪婪与非贪婪"""
content = "hello 915478897 word this is a regex demo"
result = re.match("^he.*(\d+).*demo",content)
print(result)
print(result.group())
print(result.group(1))
*# (贪婪)输出下面结果:
*# 因为\d没有具体匹配几个,前面的.*就会尽可能多的去匹配 就把91547889也匹配进去了,只给\d留了个7 所以最后的结果是7
*# <re.Match object; span=(0, 41), match='hello 915478897 word this is a regex demo'>
*# hello 915478897 word this is a regex demo
content = "hello 915478897 word this is a regex demo"
result = re.match("^he.*?(\d+).*demo",content)
print(result)
print(result.group())
print(result.group(1))
*# (非贪婪)输出下面结果:
*# 加了?就变非贪婪了 当匹配单9时\d就可以匹配了 .*?就不仔去匹配 .*?就会尽可能少的去匹配**
**# <re.Match object; span=(0, 41), match='hello 915478897 word this is a regex demo'>**
**# hello 915478897 word this is a regex demo****
*# 915478897****
*# 如果匹配结果在字符串结尾 .*?就有可能匹配不到任何内容了 例如:**
content = "hello 915478897 word this is a regex demo"
result1 = re.match("hello 915478897 word this is a(.*?)",content)
result2 = re.match("hello 915478897 word this is a(.*)",content)
print("result1", result1.group(1))
print("result1", result2.group(1))
*# 结果如下:
*# result1
*# result1 regex demo
"""修饰符"""
content = """hello 54234 world this
is a regex demo
"""
*# result = re.match("^he.*?(\d+).*?demo", content)
*# print(result.group(1))
*# 结果如下报错信息
*# AttributeError: 'NoneType' object has no attribute 'group'
*# 报错的意思是说正则表达式没有匹配到任何内容,返回为none,而我们有调用了group()方法导致attribute
*# 原因是因为 . 只能匹配除换行符外的任意字符 这时加re.S 即可**
result = re.match("^he.*?(\d+).*?demo", content, re.S)
print(result.group(1))
*# 此时结果为:
**# 54234
"""转义匹配"""
content = "(百度)www.baidu.com"
result = re.match("\(百度\)www\.baidu\.com", content)
print(result)
**# 结果为:<re.Match object; span=(0, 17), match='(百度)www.baidu.com'>
"""2.search()"""
**# search()方法在匹配时会扫描整个字符串,然后返回第一个匹配成功的结果。也就是说正则表达式可以是字符串的一部分,在匹配时i,search()方法会依次扫描字符串知道找到第一个符合规则的结果,然后返回匹配内容,如果没有找到就返回None
html = """<div id=“songs-list”>
<h2 class="title">经典老歌</h2>
...
<ul id="list class="list-group">
<li data-view="2">一路有你</li>
<li data-view="7">
<a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
</li>
<li data-view="4" class="active">
<a href="/3.mp3" singer="齐秦">往事随风</a>
</li>
<li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
...
"""
result = re.search('<li.*?active.*?singer="(.*?)">(.*?)</a>', html, re.S)
print(result.group(1))
print(result.group(2))
*# 此时结果为:
*# 齐秦
*# 往事随风
*# 如果正则表达式中不带active,由于search()方法会返回第一个符合条件的匹配目标,后面的就不匹配了,结果就变了
result = re.search('<li.*?singer="(.*?)">(.*?)</a>', html, re.S)
print(result.group(1))
print(result.group(2))
*# 此时结果为:
*# 任贤齐
*# 沧海一声笑
*# 前面两次都带了re.S修饰符,这使得.*?可以匹配换行符,如果去掉后:
result = re.search('<li.*?singer="(.*?)">(.*?)</a>', html)
print(result.group(1))
print(result.group(2))
*# 此时结果为:
*# beyond
*# 光辉岁月
"""3.findall()"""
*# findall()方法可以获取匹配正则表达式的所有内容
results = re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>', html, re.S)
print(results)
print(type(results))
for result in results:
print(result)
print(result[0], result[1], result[2])
*# 运行结果如下
*# [('/2.mp3', '任贤齐', '沧海一声笑'), ('/3.mp3', '齐秦', '往事随风'), ('/4.mp3', 'beyond', '光辉岁月')]
*# <class 'list'>
*# ('/2.mp3', '任贤齐', '沧海一声笑')
*# /2.mp3 任贤齐 沧海一声笑
*# ('/3.mp3', '齐秦', '往事随风')
*# /3.mp3 齐秦 往事随风
*# ('/4.mp3', 'beyond', '光辉岁月')
*# /4.mp3 beyond 光辉岁月
"""4.sub()"""
*# 除了使用正则表达式提取信息外,有时候还需要借助他来修改文本。这时就可以用sub()方法
content = "fgo24sfz9x7a6s0a"
content = re.sub("\d+", "", content)
print(content)
*# 此时输出结果为:
*# fgosfzxasa
*# 第一个参数\d+匹配来匹配所有的数字,第二个参数为替换成的字符串
html = re.sub("<a.*?>|</a>", "", html, re.S)
print(html)
html = re.sub("<li.*?>|</li>", "", html, re.S)
print(html)
*# 结果为:
*# <div id=“songs-list”>*
*# <h2 class="title">经典老歌</h2>
*# ...
*# <ul id="list class="list-group">
*# <li data-view="2">一路有你</li>
*# <li data-view="7">
*# 沧海一声笑
*# </li>
*# <li data-view="4" class="active">
*# 往事随风
*# </li>
*# <li data-view="6">光辉岁月</li>
*# ...
#
*# <div id=“songs-list”>
*# <h2 class="title">经典老歌</h2>
*# ...
*# <ul id="list class="list-group">
*# 一路有你
#
*# 沧海一声笑
#
#
*# 往事随风
#
*# 光辉岁月**
# ...
"""6.compile()"""
*# 前面的方法都是用来处理字符串的方法,而这个方法可以将正则字符串编译成正则表达式对象,以便在后面的匹配中复用
content1 = "2020-10-25 20:00"
content2 = "2020-10-27 21:00"
content3 = "2020-10-29 22:00"
pattern = re.compile("\d{2}:\d{2}")
result1 = re.sub(pattern, "", content1)
result2 = re.sub(pattern, "", content2)
result3 = re.sub(pattern, "", content3)
print(result1, result2, result2)
*# 结果为:
*# 2020-10-25 2020-10-27 2020-10-27
"""附"""
"""
常用匹配规则
\w 匹配字母、数字下划线
\W 匹配不是字母、数字下划线的字符
\s 匹配任意空白字符
\S 匹配任意非空字符
\d 匹配任意数字
\D 匹配任意非数字的字符
\A 匹配字符串的开头
\Z 匹配字符串结尾,如果在换行,只匹配到换行前的结束字符串
\z 匹配字符串结尾,如果在换行,同时还会匹配换行符
\G 匹配最后匹配完成的位置
\n 匹配一个换行符
\t 匹配一个制表符
^ 匹配一行字符串的开头
$ 匹配一行字符串的结尾
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符
[...] 用来表示一组字符,单独列出,比如[amk]匹配a、m或k
[^...] 不在[]中的字符,比如[^amk]匹配除了a、m或k之外的字符
* 匹配0个或者多个表达式
+ 匹配1个或者多个表达式
? 匹配0个或者1个前面的表达式定义的片段,非贪婪方式
{n} 精确匹配n个前面的表达式
{n,m} 匹配n到m次由前面正则表达式定义的片段,贪婪方式
a|b 匹配a或b
() 匹配括号内的表达水,也表示一个组
修饰符
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 匹配多行,影响^和$
re.S 是.匹配包括换行符在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响\w,\W,\B和\b
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解
"""
参考文献:
《python3网络爬虫开发实战》 --崔庆才