re模块, 分组
一. re模块
import re
findall
ret = re.findall('\d+', '3ser54gsd43sd5')
print(ret) 是一个列表, ['3', '54', '43', '5']
ret = re.findall(pattern, s, re.S)
print(ret) 在爬虫时, pattern中有.*?时, 点可以匹配换行符
search
ret = re.search('\d+', '3ser54gsd43sd5')
print(ret) 输出的是一个变量, 或None <_sre.SRE_Match object; span=(0, 1), match='3'>如果没有输出None
print(ret.group()) 输出3, 是第一个被匹配到的字符串'3'
如果匹配不到字符串, 输出print(ret.group())会报错, 可以用 if ret: printprint(ret.group())避免报错
match
从头开始匹配, 相当于search的表达式加上一个^
ret = re.match('\d+', '3ser54gsd43sd5')
print(ret) 输出<_sre.SRE_Match object; span=(0, 1), match='3'>
print(ret.group()) 输出 3
输出ret如果没有会输出None, 输出ret.group()会报错, 和search一样.
split
s = 'asd-reth-eryh-kjvv-aesf'
ret = re.split('[\w]+', s)
print(ret) 输出 ['', '-', '-', '-', '-', '']
sub
返回一个字符串
ret = re.sub(旧的, 新的, 字符串, 次数)
s = 'asd-reth-eryh-kjvv-aesf'
ret = re.sub('-', '{}', s, 2)
print(ret) # asd{}reth{}eryh{}kjvv{}aesf
subn
返回一个元组, 元组的第一个元素是和sub一样的字符串, 第二个元素是替换的次数
s = 'asd-reth-eryh-kjvv-aesf'
ret = re.subn('-', '{}', s, 2)
print(ret) # ('asd{}reth{}eryh-kjvv-aesf', 2)
compile
编译, 目的是节省用正则表达式解决问题的时间
编译 正则表达式 编译成 字节码
再多次使用的过程中不会多次编译
s = 'asd-reth-eryh-kjvv-aesf'
ret = re.compile('-')
r = ret.findall(s) 或者 r = re.findall(ret, s)
print(r) # ['-', '-', '-', '-']
r = ret.search(s) 或者 r = re.search(ret, s)
print(r)
finditer
节省使用正则表达式解决问题的内存
s = 'asd-reth-eryh-kjvv-aesf'
ret = re.finditer('-', s)
for i in ret:
print(i) # <_sre.SRE_Match object; span=(3, 4), match='-'> <_sre.SRE_Match object; span=(8, 9), match='-'> 和print(re.search())的输出是一样的
print(i.group()) # - - - -
findall 返回列表
search 返回一个None或者<_sre.SRE_Match object; span=(3, 4), match='-'> , 需要用到group()
match 返回一个None或者<_sre.SRE_Match object; span=(0, 4), match='-'> 相当于正则表达式的一开始是^的match, 需要用到group()
split 返回列表, 用正则写在前面, 把要被切割的字符串写在后面, 返回一个被切割后的列表
sub 返回字符串, 替换, 用被替换的旧的正则写在前面, 把替换的新的字符串写在后面, 把替换的变量或一串字符串写在后面
subn 返回一个元组, 元组的第一项和sub一样, 第二项是替换的次数
compile 返回re.compile('xxx') 编译, 特点是提高处理速度, 每次用re模块时, 不需要每次都编译正则模块, 可以用在findall, search, match, sub, subn, split, finditer, 可以直接写成r = re.compile() ret = a.findall(), 可以不写成re.findall()
finditer 返回一个内存地址, 特点是和迭代器一样节省内存, 如果遍历finditer的返回值, 把返回值.group()可以一次拿到一个find的值
二. 分组
分组可以更精准的找到我需要的内容
search
import re
s = 'asd-reth-eryh-kjvv-aesf'
ret = re.search('\w(\w)\w(\w)', s)
print(ret.group()) 或者 print(ret.group(0)) # 输出reth
print(ret.group(1)) # 输出e
print(ret.group(2)) # 输出h
在search中, 在正则表达式里加括号会输出迭代器的第一个结果, 同时在括号内加1会输出第一个结果的第1个括号内的内容
findall
如果需要用findall, 同时正则表达式中含有(), 需要用?:来使()不变成输出()内的内容
s = 'asd-reth-eryh-kjvv-aesf'
ret = re.findall('\w(\w)\w(\w)', s)
print(ret) # 输出[('e', 'h'), ('r', 'h'), ('j', 'v'), ('e', 'f')]
split
split在用括号括起来正则表达式时, 可以按切割的顺序, 把被切割掉的内容一起放到输出的列表里
ret = re.split('-', s)
print(ret) # 输出['asd', 'reth', 'eryh', 'kjvv', 'aesf']
ret = re.split('(-)', s)
print(ret) # 输出['asd', '-', 'reth', '-', 'eryh', '-', 'kjvv', '-', 'aesf']
取消分组优先
在正则的括号内加上?:
ret = re.findall('\d(?:\d), s)
分组命名, 用(?P<组名>正则表达式)表示
ret = re.search('(?P<con>\w)(?P<c>-)', s)
print(ret.group('con')) # 输出asd
print(ret.group('c')) # 输出-
用分组命名匹配网页源代码的<a>和</a>内的一样的内容
s = '<a>adss-asdf-asdf</a>'
pattern = '<(?P<tab>\w+)>([^<>]+)</(?P=tab)>'
ret = re.search(pattern, s)
print(ret.group()) # 输出<a>adss-asdf-asdf</a>
(?P<tab>\w+)在这里匹配到的是a, 用</(?P=tab)>设置成</和>内的内容要和(?P<tab>)一样, 如果字符串中找不到, 会报错