正则表达式本身是一种小型的、高度专业化的编程语言。Python 的 re 模块(Regular Expression 正则表达式)提供各种正则表达式的匹配操作,Python 会将正则表达式转化为字节码,利用 C 语言的匹配引擎进行深度优先的匹配。
参考:
https://www.cnblogs.com/tina-python/p/5508402.html
https://blog.csdn.net/sinat_20791575/article/details/54139404
https://www.cnblogs.com/dreamer-fish/p/5282679.html
re模块中常用功能函数
compile()
re.compile(pattern, flags=0)
编译正则表达式,返回一个 pattern 对象
pattern: 编译时用的表达式字符串
flags: 编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等。常用的flags有:
| 标志 | 含义 |
| ---------------- | -------------------------------------------------------- |
| re.S(DOTALL) | 使.匹配包括换行在内的所有字符 |
| re.I(GNORECASE) | 使匹配对大小写不敏感 |
| re.L(LOCALE) | 做本地化识别(locale-aware)匹配,法语等 |
| re.M(MULTILINE) | 多行匹配,影响^和$ |
| re.X(VERBOSE) | 该标志通过给予更灵活的格式以便将正则表达式写得更易于理解 |
| re.U | 根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B |
prog = re.compile(pattern)
result01 = prog.match(string)
result02 = prog.search(string)
result03 = prog.findall(string)
# 等价于
result = re.match(pattern, string)
match()
re.match(pattern, string, flags=0)
如果字符串的开头能匹配正则表达式,返回对应的 match 对象,否则返回None
search()
re.search(pattern, string, flags=0)
在字符串中查找,是否能匹配正则表达式,若是,返回对应的 match 对象,否则返回None
phoneMatch = re.search(r"(\d\d\d)-(\d\d\d)-(\d\d\d\d)",
"My number is 111-222-3333")
print(phoneMatch.group())
>>>'111-222-3333'
print(phoneMatch.groups())
>>>('111', '222', '3333')
print(phoneMatch.group(0))
>>>'111-222-3333'
print(phoneMatch.group(1))
>>>'111'
print(phoneMatch.group(2))
>>>'222'
print(phoneMatch.group(3))
>>>'3333'
findall()
re.findall(pattern, string, flags=0)
找到 RE 匹配的所有子串,并把它们作为一个列表返回。如果无匹配,返回空列表
re.findall(r"(\d\d\d)-(\d\d\d)-(\d\d\d\d)",
"My number is 111-222-3333; Your number is 123-555-8899")
>>>['111','222','333']
re.subn(r"n(.*?)er", "aa", "My number is 111-222-3333; Your number is 123-555-8899")
>>>('My aa is 111-222-3333; Your aa is 123-555-8899', 2)
re.findall(r"n.*?er", "My number is 111-222-3333; Your number is 123-555-8899")
>>>['number', 'number']
finditer()
re.finditer(pattern, string, flags=0)
找到 RE 匹配的所有子串,并把它们作为一个迭代器返回(没啥用)
split()
re.split(pattern, string, maxsplit=0, flags=0)
使用正则表达式分离字符串。如果用括号将正则表达式括起来,那么匹配的字符串也会被列入到list中返回。maxsplit是分离的次数,maxsplit=1分离一次,默认为0,不限制次数
text = "JGood is a handsome boy, he is cool, clever, and so on..."
re.sub(r'\s+', '-', text)
>>>'JGood-is-a-handsome-boy,-he-is-cool,-clever,-and-so-on...'
sub()
re.sub(pattern, repl, string, count=0, flags=0)
找到 RE 匹配的所有子串,并将其用一个不同的字符串替换。可选参数 count 是模式匹配后替换的最大次数;count 必须是非负整数。缺省值是 0 表示替换所有的匹配。如果无匹配,字符串将会无改变地返回
subn()
subn(pattern, repl, string, count=0, flags=0)
返回元组,结果和替换次数
使用总结
日常使用search和findall
compile基本不用使用
match与search与findall的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配
re.match('[\d]',"abc33") >>>None re.search('[\d]',"abc33").group() >>>3 re.findall('[\d]',"abc33") >>>['3', '3']
正则表达式符号
点号"."
- 点号可以代表任意除\n以外的字符
- 一个点号代表一个字符,相当于占位符
- chenjunpeng -> chenjun...g
星号"*"
- 星号代表它前面的子表达式0次到多次
- chenjunpeng -> chen.*g
- chennnnnnn -> chen*
- chen -> che*
问号"?"
- 问好代表它前面的子表达式0次或者1次
- chenjunpeng -> Chinju.?peng
- chenjunpeng -> chenu?junpeng
加号"+"
- 加号代表它前面的子表达式1次或者多次
- Batwoman ->Bat(wo)+man
花括号{}
- {2,5}
- {2,5}?
- 匹配制定次数
- Batwowowoman ->Bat(wo){2,5}man
管道符"|"
括号()
- 只要括号里面的内容
- 括号内容相当一个完整的子表达式
转义字符" "
- 反斜杠不能单独使用
- 让特殊字符变为普通字符:"\*"
- 让普通字符变为特殊字符:"\d" 代表数字
启始"^"
结尾"$"
提取数字
- \d
- 正则表达式里面,使用 “\d” 来表示一位数字。这里要强调一下,\d 虽然是由从左上向右下的斜杠和字母d构成的,但是我们要把\d看成是一个正则表达式符号整体。从左上向右下的斜杠,名字叫做“反斜杠”,在正则表达式中是作为转义字符,不能单独使用。
- 如果要提取两个数字,我们可以使用 \d\d,如果要提取三个数字,我们可以使用\d\d\d,但是问题来了,如果我们不知道有这个数有多少位怎么办呢?就需要使用上一课讲到的 + 号。+ 号可以匹配它前面的符号一次或者多次。所以使用 \d+,可以表示一个任意位数的数字。
提取文本
.* 贪心算法
**.*?** 非贪心算法
对于文本来说,我们在爬虫中一般使用 .*? 这三个符号来完成。
我们知道点号表示任意非换行符的字符,*号表示匹配它前面的字符零次或者任意多次。所以 .* 表示匹配一串任意长度的字符串任意次。这个时候必须在 .* 的前后加其他的符号来限定范围,否则得到的结果就是原来的整个字符串。
如果在 .* 的后面加一个问号变成 .*? ,那么可以得到什么样的结果呢?问号表示匹配它前面的符号0次或者1次。于是 .*? 的意思就是,匹配一个能满足要求的最短字符串。
换行符\n隔断处理
字符类
实例 描述 [Pp]ython 匹配 "Python" 或 "python" rub[ye] 匹配 "ruby" 或 "rube" [aeiou] 匹配中括号内的任意一个字母 [0-9] 匹配任何数字。类似于 [0123456789] [a-z] 匹配任何小写字母 [A-Z] 匹配任何大写字母 [a-zA-Z0-9] 匹配任何字母及数字 [^aeiou] 除了aeiou字母以外的所有字符 [^0-9] 匹配除了数字外的字符 特殊字符类
实例 描述 . 匹配除 "\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_]'。
贪心和非贪心匹配
Python的正则表达式匹配模式默认是贪心匹配
问号模式是非贪心模式
# 贪心
re.search(r"\d{2,5}", r"123456").group()
>>> '12345'
# 非贪心
re.search(r"\d{2,5}?", r"12346").group()
>>> '12'
# 贪心
re.findall(r"n(.*)er", "My number is 111-222-3333; Your number is 123-555-8899")
>>>['umber is 111-222-3333; Your numb']
# 非贪心
re.findall(r"n(.*?)er", "My number is 111-222-3333; Your number is 123-555-8899")
>>>['umb', 'umb']