赞
踩
'.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
'*' 匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 结果为['abb', 'ab', 'a']
'+' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?' 匹配前一个字符1次或0次
'{m}' 匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
'|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c
'\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的
'\Z' 匹配字符结尾,同$
'\d' 匹配数字0-9
'\D' 匹配非数字
'\w' 匹配[A-Za-z0-9]
'\W' 匹配非[A-Za-z0-9]
's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t'
'(?P<name>...)' 分组匹配
re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city")
结果{'province': '3714', 'city': '81', 'birthday': '1993'}
re.match 从头开始匹配
re.search 匹配包含
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符当做列表分隔符
re.sub 匹配字符并替换
在Python的string前面加上‘r’, 是为了告诉编译器这个string是个raw string,
不要转意backslash '\' 。
例如,\n 在raw string中,是两个字符,\和n, 而不会转意为换行符。
由于正则表达式和 \ 会有冲突,因此,当一个字符串使用了正则表达式后,最好在前面加上'r'。
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
M(MULTILINE): 多行模式,改变'^'和'$'的行为
S(DOTALL): 点任意匹配模式,改变'.'的行为
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。
本文主要介绍Python中常用的正则表达式处理函数。
re.match(pattern, string, flags=0)
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
匹配对象方法 | 描述 |
---|---|
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
实例:
#!/usr/bin/python
import re
line = "Cats are smarter than dogs"
matchObj = re.match(r'(.*) are (.*?) .*', line, re.M | re.I)
if matchObj:
print ("matchObj.group() : ", matchObj.group())
print ("matchObj.group(1) : ", matchObj.group(1))
print ("matchObj.group(2) : ", matchObj.group(2))
else:
print ("No match!!")
以上实例执行结果如下:
matchObj.group() : Cats are smarter than dogs
matchObj.group(1) : Cats
matchObj.group(2) : smarter
re.search(pattern, string, flags=0)
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
匹配对象方法 | 描述 |
---|---|
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
#!/usr/bin/python
import re
line = "Cats are smarter than dogs"
searchObj = re.search(r'(.*) are (.*?) .*', line, re.M | re.I)
if searchObj:
print ("searchObj.group() : ", searchObj.group())
print ("searchObj.group(1) : ", searchObj.group(1))
print ("searchObj.group(2) : ", searchObj.group(2))
else:
print ("No search!!")
searchObj.group() : Cats are smarter than dogs
searchObj.group(1) : Cats
searchObj.group(2) : smarter
#!/usr/bin/python
import re
line = "Cats are smarter than dogs";
matchObj = re.match(r'dogs', line, re.M | re.I)
if matchObj:
print ("match --> matchObj.group() : ", matchObj.group())
else:
print ("No match!!")
matchObj = re.search(r'dogs', line, re.M | re.I)
if matchObj:
print ("search --> matchObj.group() : ", matchObj.group())
else:
print ("No match!!")
No match!!
search --> matchObj.group() : dogs
re.sub(pattern, repl, string, count=0, flags=0)
# !/usr/bin/python
import re
phone = "2004-959-559 # This is Phone Number"
# Delete Python-style comments
num = re.sub(r'#.*$', "", phone)
print ("Phone Num : ", num)
# Remove anything other than digits
num = re.sub(r'\D', "", phone)
print ("Phone Num : ", num)
Phone Num : 2004-959-559
Phone Num : 2004959559
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
常用符号:点号,星号,问号与括号(小括号)
. :匹配任意字符,换行符\n除外
* :匹配前一个字符0次或无限次
? :匹配前一个字符0次或1次
.* :贪心算法
.*? :非贪心算法
() :括号内的数据作为结果返回
常用方法:findall, search, sub
findall:匹配所有符合规律的内容,返回包含结果的列表
search:匹配并提取第一个规律的内容,返回一个正则表达式对象(object)
sub:替换符合规律的内容,返回替换后的值
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
代码/语法 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
代码/语法 | 说明 |
---|---|
\W | 匹配任意不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
分类 | 代码/语法 | 说明 |
---|---|---|
捕获 | (exp) | 匹配exp,并捕获文本到自动命名的组里 |
(?<name>exp) | 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp) | |
(?:exp) | 匹配exp,不捕获匹配的文本,也不给此分组分配组号 | |
零宽断言 | (?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 | |
(?!exp) | 匹配后面跟的不是exp的位置 | |
(?<!exp) | 匹配前面不是exp的位置 | |
注释 | (?#comment) | 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 |
代码/语法 | 说明 |
---|---|
*? | 重复任意次,但尽可能少重复 |
+? | 重复1次或更多次,但尽可能少重复 |
?? | 重复0次或1次,但尽可能少重复 |
{n,m}? | 重复n到m次,但尽可能少重复 |
{n,}? | 重复n次以上,但尽可能少重复 |
.
import re
a = 'xzx23'
b = re.findall('x.', a)
print b
-
['xz', 'x2']
.
是一个占位符,一个.
代表一个符号*
import re
a = 'xyxy123'
b = re.findall('x*', a)
print(b)
['x', '', 'x', '', '', '', '', '']
依次匹配字符,有则显示,无则显示''
(空)。
?
import re
a = 'xy123'
b = re.findall('x?', a)
print(b)
['x', '', '', '', '', '']
*
一样,前面附加其他的符号将做非贪心限制
.*
import re
secret_code = 'ghkj08hs68xxIxxa14kgj4w314exxlovexxbvk14rgjhxxyouxxfj4286ykjhag2'
b = re.findall('xx.*xx', secret_code)
print(b)
['xxIxxa14kgj4w314exxlovexxbvk14rgjhxxyouxx']
.*?
import re
secret_code = 'ghkj08hs68xxIxxa14kgj4w314exxlovexxbvk14rgjhxxyouxxfj4286ykjhag2'
b = re.findall('xx.*?xx', secret_code)
print(b)
['xxIxx', 'xxlovexx', 'xxyouxx']
(.*?)
import re
secret_code = 'ghkj08hs68xxIxxa14kgj4w314exxlovexxbvk14rgjhxxyouxxfj4286ykjhag2'
b = re.findall('xx(.*?)xx', secret_code)
print(b)
['I', 'love', 'you']
()
包围所需要的内容,括号内的内容作为结果返回,不需要的内容放在括号外面
import re
secret_code = '''ghkj08hs68xxIxxa14kgj4w314exxlove
xxbvk14rgjhxxyouxxfj4286ykjhag2'''
#love后有换行符
b = re.findall('xx(.*?)xx', secret_code)
print(b)
# 因为.不能匹配换行符。所以会一行为一个搜索项去找。匹配任何字符除了新的一行
['I', 'bvk14rgjh']
re.S
import re
secret_code = '''ghkj08hs68xxIxxa14kgj4w314exxlove
xxbvk14rgjhxxyouxxfj4286ykjhag2'''
#love后有换行符
b = re.findall('xx(.*?)xx', secret_code, re.S)
print(b)
# re.S让.匹配所有行,包括了换行符(以\n的形式出现)
['I', 'love\n', 'you']
对比search和findall的区别
search 找到一个后返回,不继续,大大提高效率
findall遍历全部,找到尽可能多的项
import re
s2 = '''ghkj08hs68xxIxx123xxlove
xxbvk14rgjhxxfj4286ykjhag2'''
b = re.search('xx(.*?)xx(.*?)xx', s2, re.S).group(1)
print(b)
c = re.search('xx(.*?)xx(.*?)xx', s2, re.S).group(2)
print(c)
d = re.search('xx(.*?)xx(.*?)xx', s2, re.S).group(3)
print(d)
Traceback (most recent call last):
File "D:/WorkSpace/python/Django/test.py", line 7, in <module>
d = re.search('xx(.*?)xx(.*?)xx', s2, re.S).group(3)
IndexError: no such group
I
123
group
是按括号顺序匹配
import re
s2 = '''ghkj08hs68xxIxx123xxlovexxbvk14rgjhxxfj4286ykjhag2'''
f2 = re.findall('xx(.*?)xx123xx(.*?)xx', s2, re.S)
print (f2)
print (f2[0][1])
[('I', 'love')]
love
每一个匹配项为第一级列表,括号为二级列表
re.sub(pattern, repl, string, count=0, flags=0)
- 找到 RE 匹配的所有子串,并将其用一个不同的字符串替换。
第一个参数:pattern
pattern,表示正则中的模式字符串
第二个参数:repl
repl,就是replacement,被替换,的字符串的意思。
第三个参数:string
string,即表示要被处理,要被替换的那个string字符串。
-
- 第四个参数:可选参数 count 是模式匹配後替换的最大次数;count 必须是非负整数。
- 缺省值是 0 表示替换所有的匹配。如果无匹配,字符串将会无改变地返回。
re.subn(pattern, repl, string, count=0, flags=0)
- 与re.sub方法作用一样,但返回的是包含新字符串和替换执行次数的两元组。
import re
s = '123abcssfasdfas123'
output = re.sub('123(.*?)123', '123789123', s)
print (output)
# sub将符合条件的()内内容提换
123789123
import re
inputStr = "hello 123 world 456"
replacedStr = re.sub("\d+", "222", inputStr)
print (replacedStr)
hello 222 world 222
from re import findall, search, S
最好不要引入,因为S等容易和变量等混淆,引起歧义
import re
secret_code = '''ghkj08hs68xxIxxa14kgj4w314exxlove
xxbvk14rgjhxxyouxxfj4286ykjhag2'''
pattern = 'xx(.*?)xx'
new_pattern = re.compile(pattern, re.S)
b = re.findall(new_pattern, secret_code)
print (b)
['I', 'love\n', 'you']
import re
a = 'dfhkgh43gfhja873y5t2167715'
b = re.findall('(\d+)', a)
print (b)
['43', '873', '5', '2167715']
import re
old_url = 'http://www.jikexueyuan.com/course/android/?pageNum=2'
total_page = 20
f = open('text.txt', 'r')
html = f.read()
f.close()
title = re.search('<title>(.*?)</title>', html, re.S).group(1)
print title
<html>
<head>
<title>极客学院爬虫测试</title>
</head>
<body>
<div class="topic"><a href="http://jikexueyuan.com/welcome.html">欢迎参加《Python定向爬虫入门》</a>
<div class="list">
<ul>
<li><a href="http://jikexueyuan.com/1.html">这是第一条</a></li>
<li><a href="http://jikexueyuan.com/2.html">这是第二条</a></li>
<li><a href="http://jikexueyuan.com/3.html">这是第三条</a></li>
</ul>
</div>
</div>
</body>
</html>
极客学院爬虫测试
link = re.findall('href="(.*?)"', html, re.S)
for each in link:
print each
http://jikexueyuan.com/welcome.html
http://jikexueyuan.com/1.html
http://jikexueyuan.com/2.html
http://jikexueyuan.com/3.html
先爬大再爬小
text_fied = re.findall('<ul>(.*?)</ul>', html, re.S)[0]
the_text = re.findall('">(.*?)</a>', text_fied, re.S)
for every_text in the_text:
print every_text
2)用sub实现翻页功能
for i in range(2, total_page+1):
new_link = re.sub('pageNum=\d+', 'pageNum=%d'%i, old_url, re.S)
print new_link
完整代码
import re
a = 'xzx23'
# . :匹配任意字符,换行符\n除外
# 点.是一个占位符,一个.代表一个符号
b = re.findall('x.', a)
print(". :匹配任意字符,换行符\\n除外:",b)
# * :匹配前一个字符0次或无限次
# 依次匹配字符,有则显示,无则显示''(空)。
c= re.findall('x*', a)
print("* :匹配前一个字符0次或无限次:",c)
# 问号?
# ? :匹配前一个字符0次或1次
# 单独与*一样,前面附加其他的符号将做非贪心限制
d= re.findall('x?', a)
print("? :匹配前一个字符0次或1次:",d)
# 贪心.*
# 只要满足条件全部显示,贪心算法
secret_code = 'ghkj08hs68xxIxxa14kgj4w314exxlovexxbvk14rgjhxxyouxxfj4286ykjhag2'
e = re.findall('xx.*xx', secret_code)
print ("贪心.*:",e)
# 非贪心.*?
secret_code = 'ghkj08hs68xxIxxa14kgj4w314exxlovexxbvk14rgjhxxyouxxfj4286ykjhag2'
f = re.findall('xx.*?xx', secret_code)
print ("非贪心.*?:",f)
# () :括号内的数据作为结果返回
# ()包围所需要的内容,括号内的内容作为结果返回,不需要的内容放在括号外面
secret_code = 'ghkj08hs68xxIxxa14kgj4w314exxlovexxbvk14rgjhxxyouxxfj4286ykjhag2'
g = re.findall('xx(.*?)xx', secret_code)
print ("非贪心.*?:",g)
# sub将符合条件的()内内容提换
# sub:替换符合规律的内容,返回替换后的值
s = '123abcssfasdfas123'
output = re.sub('123(.*?)123', '123789123', s)
print ('sub将符合条件的()内内容提换:',output)
# re.S让.匹配所有行,包括了换行符(以\n的形式出现)
# search 找到一个后返回,不继续,大大提高效率
# findall遍历全部,找到尽可能多的项
s2 = '''ghkj08hs68xxIxx123xxlove
xxbvk14rgjhxxfj4286ykjhag2'''
b = re.search('xx(.*?)xx(.*?)xx', s2, re.S)
print ('search 找到一个后返回,不继续,大大提高效率:',b)
# 输出
# < _sre.SRE_Match
# object;
# span = (10, 20), match = 'xxIxx123xx' >
# group是按括号顺序匹配
b = re.search('xx(.*?)xx(.*?)xx', s2, re.S).group(1)
print ('search 找到一个后返回,不继续,大大提高效率:',b)
# .group(3)报错
# Traceback (most recent call last):
# File "D:/WorkSpace/python/PycharmProjects/爬虫/代码/Python-master/ReDemo.py", line 61, in <module>
# b = re.search('xx(.*?)xx(.*?)xx', s2, re.S).group(3)
# IndexError: no such group
# 每一个匹配项为第一级列表,括号为二级列表
s2 = '''ghkj08hs68xxIxx123xxlovexxbvk14rgjhxxfj4286ykjhag2'''
f2 = re.findall('xx(.*?)xx123xx(.*?)xx', s2, re.S)
print ('每一个匹配项为第一级列表,括号为二级列表:',f2[0][1])
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。