'.' 默认匹配除\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
...)' 分组匹配re.search("(?P
[0-9]{4})(?P ,"371481199306143242").groupdict("city")[0-9]{2})(?P [0-9]{4})" 结果{'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)
实例:
#!/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)
#!/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
常用符号:点号,星号,问号与括号(小括号)
. :匹配任意字符,换行符\n除外
* :匹配前一个字符0次或无限次
? :匹配前一个字符0次或1次
.* :贪心算法
.*? :非贪心算法
() :括号内的数据作为结果返回
常用方法:findall, search, sub
findall:匹配所有符合规律的内容,返回包含结果的列表
search:匹配并提取第一个规律的内容,返回一个正则表达式对象(object)
sub:替换符合规律的内容,返回替换后的值
.
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('
(.*?) ', 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('
(.*?)
', html, re.S)[0]the_text = re.findall('">(.*?)', 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
# 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])