什么是正则表达式
世界上信息非常多,而我们关注的信息有限。假如我们希望只提取出关
注的数据,此时可以通过一些表达式进行提取,正则表达式就是其中一
种进行数据筛选的表达式。
原子
原子是正则表达式中最基本的组成单位,每个正则表达式中至少要包含
一个原子。常见的原子类型有:
- a普通字符作为原子
- b非打印字符作为原子
- c通用字符作为原子
- d原子表
正则表达式函数
正则表达式函数有re.match()函数、re.search()函数、全局匹配函数、 re.sub()函数。
re.search
re.search 扫描整个字符串并返回第一个成功的匹配。
import re
pat = "yue"
string = "http://iqianyue.com"
result = re.search(pat,string)
print(result)
输出结果如下:
<_sre.SRE_Match object; span=(12, 15), match='yue'>
re.match
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
import re
pat = "yue"
string = "yuehttp://iqyueianyue.com"
result = re.match(pat,string)
print(result)
输出结果如下:
<_sre.SRE_Match object; span=(0, 3), match='yue'>
全局匹配函数 re.compile().findall():
扫描整个字符串并以列表的形式返回符合条件的匹配值
import re
pat = "p.*?n"
string = "abcpythonjgkhappynn"
result = re.compile(pat).findall(string)
print(result)
输出结果如下:
['python', 'ppyn']
re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
模式修正符
所谓模式修正符,即可以在不改变正则表达式的情况下,通过模式修正符改变正则表达式的含义,从而实现一些匹配结果的调整等功能。
正则表达式中常用的模式修正符有i、g、m、s、x、e等。它们之间可以组合搭配使用。
- 修正符:i不区分大小写的匹配;
- 修正符:m将字符串视为多行,不管是那行都能匹配;
- 修正符:s将字符串视为单行,换行符作为普通字符;
- 修正符:x将模式中的空白忽略;
- 修正符:A强制从目标字符串开头匹配;
- 修正符:D如果使用$限制结尾字符,则不允许结尾有换行;
- 修正符:U只匹配最近的一个字符串;不重复匹配;
举例如下:
import re
pat = "bai"
string = "http://www.Baidu.com"
result = re.search(pat,string,re.I)#不区分大小写
print(result)
贪婪模式与懒惰模式
贪婪模式的核心点就是尽可能多的匹配,而懒惰模式的核心点就是尽可能少的匹配(更精确的定位)。
import re
pat1 = "p.*y"#贪婪模式(尽可能多的匹配)
pat2 = "p.*?y"#懒惰模式(尽可能少的匹配)
string = "abcpythonfghappy"
result1 = re.search(pat1,string)
result2 = re.search(pat2,string)
print(result1)
print(result2)
输出结果如下:
<_sre.SRE_Match object; span=(3, 16), match='pythonfghappy'>
<_sre.SRE_Match object; span=(3, 5), match='py'>
正则表达式实例
实例 | 描述 |
---|---|
python | 匹配 "python" |
[Pp]ython | 匹配 "Python" 或 "python" |
rub[ye] | 匹配 "ruby" 或 "rube" |
[aeiou] | 匹配中括号内的任意一个字母 |
[0-9] | 匹配任何数字。类似于 [0123456789] |
[a-z] | 匹配任何小写字母 |
[A-Z] | 匹配任何大写字母 |
[a-zA-Z0-9] | 匹配任何字母及数字 |
[^aeiou] | 除了aeiou字母以外的所有字符 |
. | 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。 |
\d | 匹配一个数字字符。等价于 [0-9]。 |
\D | 匹配一个非数字字符。等价于 [^0-9]。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\w | 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。 |
\W | 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。 |
非打印字符
元字符 | 描述 |
---|---|
\cx | 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。 |
\f | 匹配一个换页符。等价于 \x0c 和 \cL。 |
\n | 匹配一个换行符。等价于 \x0a 和 \cJ。 |
\r | 匹配一个回车符。等价于 \x0d 和 \cM。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\t | 匹配一个制表符。等价于 \x09 和 \cI。 |
\v | 匹配一个垂直制表符。等价于 \x0b 和 \cK。 |
特殊字符
特别字符 | 描述 |
---|---|
$ | 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 $。 |
( ) | 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。 |
* | 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。 |
+ | 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。 |
. | 匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。 |
[ | 标记一个中括号表达式的开始。要匹配 [,请使用 \[。 |
? | 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。 |
\ | 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\' 匹配 "",而 '(' 则匹配 "("。 |
^ | 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。 |
{ | 标记限定符表达式的开始。要匹配 {,请使用 \{。 |
指明两项之间的一个选择。 |
限定符
字符 | 描述 |
---|---|
* | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。 |
+ | 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。 |
? | 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等价于 {0,1}。 |
{n} | n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。 |
{n,} | n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。 |
{n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。 |
python中正则表达式常用场景
- 匹配.com或.cn网址
import re
pat = "[a-zA-Z]+://[^\s]+[.com|.cn]"
string = '<a href="http://www.baidu.com></a>">'
result = re.compile(pat).findall(string)
print(result)
输出如下:
['http://www.baidu.com']
- 匹配JavaScript带标签的网址
比如从 https://read.douban.com/provider/all中将所有出版社提取出来,把无关信息过滤掉。<div class="name">北京师范大学出版社</div>
import urllib
import re
# <div class="name">北京师范大学出版社</div>
url = "https://read.douban.com/provider/all"
pat = '<div class="name">(.*?)</div>'
data = urllib.request.urlopen(url).read().decode("utf-8","ignore")
result = re.compile(pat).findall(data)
print(result)
输出结果如下:
['博集天卷', '北京邮电大学出版社', '北京师范大学出版社', '百花洲文艺出版社', '百花文艺出版社', '长江数字', '重庆大学出版社', '东方文萃', '读客图书', '电子工业出版社', '当代中国出版社', '第一财经周刊', '豆瓣阅读同文馆', '豆瓣', '豆瓣阅读', '豆瓣阅读出版计划', '东方巴别塔文化', '凤凰壹力', '凤凰悦世泓文', '凤凰联动', 'Fiberead', '复旦大学出版社', '凤凰雪漫', '果壳阅读', '果麦文化', '广西师范大学出版社', '杭州蓝狮子文化创意股份有限公司', '后浪出版公司', '华东师范大学出版社', '华章数媒', '汉唐阳光', '华文时代', '湖北人民出版社', '华章同人', '华夏盛轩', '海豚出版社', '虹膜出版', '化学工业出版社', '华中科技大学出版社', '湖北科学技术出版社', '黑龙江北方文艺出版社', '华文经典', 'HarperCollins', '聚石文华', '金城出版社', '简书', '今古传奇', '江苏人民出版社', '九州幻想', '科幻世界', '酷威文化', '理想国', '漓江出版社', '磨铁数盟', '宁波出版社', '南方人物周刊', 'ONE·一个', '浦睿文化', 'Parkstone International', 'Packt Publishing', '清华大学出版社', '青岛出版社', '《人物》杂志', '人民文学出版社', '人民邮电出版社', '儒意欣欣', '人民东方出版传媒', '人民文学杂志社', '上海九久读书人', '世纪文景', '四川数字出版传媒有限公司', '上海译文出版社', '时代华文', '上海雅众文化', '世纪文睿', '时代华语', '商务印书馆', '生活·读书·新知三联书店', '上海社会科学院出版社', '社会科学文献出版社', '山西春秋电子音像出版社', '时代数联', '陕西人民出版北京分公司', '《书城》杂志', '世图北京', '四川文艺出版社', '上海文艺出版社', '上海人民出版社', '上海交通大学出版社', '斯坦威图书', '上海人民美术出版社', '图灵社区', 'Trajectory', '武汉大学出版社北京分社', '万有图书', '我和豆瓣', '新经典文化电子书', '新星出版社', '新华先锋文化传媒', '雪球', '悬疑世界', '现代出版社', '西南财经大学出版社', '新华出版社', '新华先锋出版科技', '译林出版社', '译言·东西文库', '译言·古登堡计划', '悦读纪', '阳光博客', '悦读名品', '燕山出版社', '阅文集团华文天下', '中信出版社', '中国人民大学出版社', '中作华文', '中国轻工业出版社', '紫图图书', '浙版数媒', '中央编译出版社', '知乎', '中国国家地理图书部', '浙江摄影出版社', '中国经济出版社', '中国青年出版社', '中国民主法制出版社', '中国传媒大学出版社', '中国言实出版社', '浙江大学出版社', '湛庐文化', '浙江文艺出版社', '中华书局']