【spider03】正则表达式

什么是正则表达式

正则表达式是对字符串操作的一种逻辑公式,就是用实现定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

非Python独有,re模块实现

tool.oschina.net 在线正则表达式测试

常见匹配模式

^ 匹配字符串的开头

$ 匹配字符串的末尾。

. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。

[…] 用来表示一组字符,单独列出:[amk] 匹配 ‘a’,‘m’或’k’

[^…] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。

re* 匹配0个或多个的表达式。

re+ 匹配1个或多个的表达式。

re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式

re{ n} 精确匹配 n 个前面表达式。例如, o{2} 不能匹配 “Bob” 中的 “o”,但是能匹配"food" 中的两个 o。

re{ n,} 匹配 n 个前面表达式。例如, o{2,} 不能匹配"Bob"中的"o",但能匹配"foooood"中的所有 o。“o{1,}” 等价于 “o+”。“o{0,}” 则等价于 “o*”。

re{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式

a| b 匹配a或b

(re) 匹配括号内的表达式,也表示一个组

(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。

(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。

(?: re) 类似 (…), 但是不表示一个组

(?imx: re) 在括号中使用i, m, 或 x 可选标志

(?-imx: re) 在括号中不使用i, m, 或 x 可选标志

(?#…) 注释.

(?= re) 前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。

(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功

(?> re) 匹配的独立模式,省去回溯。

\w 匹配字母数字及下划线

\W 匹配非字母数字及下划线

\s 匹配任意空白字符,等价于 [\t\n\r\f].

\S 匹配任意非空字符

\d 匹配任意数字,等价于 [0-9].

\D 匹配任意非数字

\A 匹配字符串开始

\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。

\z 匹配字符串结束

\G 匹配最后匹配完成的位置。

\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。

\B 匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。

\n, \t, 等. 匹配一个换行符。匹配一个制表符。等

\1…\9 匹配第n个分组的内容。

\10 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。

re.I 使匹配对大小写不敏感

re.L 做本地化识别(locale-aware)匹配

re.M 多行匹配,影响 ^ 和 $

re.S 使 . 匹配包括换行在内的所有字符

re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.

re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

re.match

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none

re.match(pattern,string,flags=0)

最常规的匹配

content = 'Hello 123 4567 World_This is a Regex Demo'
print(len(content))
result = re.match('^Hello\s\d{3}\s\d{4}\s\w{10}.*Demo$',content)
print(result)
print(result.group())
print(result.span())
41
<_sre.SRE_Match object; span=(0, 41), match='Hello 123 4567 World_This is a Regex Demo'>
Hello 123 4567 World_This is a Regex Demo
(0, 41)

泛匹配

content = 'Hello 123 4567 World_This is a Regex Demo'
print(len(content))
result = re.match('^Hello.*Demo$',content)
print(result)
print(result.group())
print(result.span())
41
<_sre.SRE_Match object; span=(0, 41), match='Hello 123 4567 World_This is a Regex Demo'>
Hello 123 4567 World_This is a Regex Demo
(0, 41)

匹配目标

content = 'Hello 123 4567 World_This is a Regex Demo'
print(len(content))
result = re.match('^Hello\s(\d+)\s(\d+)\s\w{10}.*Demo$',content)
print(result)
print(result.group(1))
print(result.group(2))
print(result.span())
41
<_sre.SRE_Match object; span=(0, 41), match='Hello 123 4567 World_This is a Regex Demo'>
123
4567
(0, 41)

贪婪匹配

import re

content = ‘Hello 1234567 World_This is a Regex Demo’
result = re.match(’^He.*(\d+).*Demo$’,content)
print(result)
print(result.group(1))#.*会尽可能匹配多的字符

非贪婪匹配

import re

content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^He.*?(\d+).*Demo$',content)
print(result)
print(result.group(1))#.*会尽可能匹配少的字符
<_sre.SRE_Match object; span=(0, 40), match='Hello 1234567 World_This is a Regex Demo'>
1234567

匹配模式

import re

content = '''Hello 1234567 World_This
is a Regex Demo
'''
result = re.match('^He.*?(\d+).*?Demo$',content,re.S)
print(result)
print(result.group(1))
<_sre.SRE_Match object; span=(0, 40), match='Hello 1234567 World_This\nis a Regex Demo'>
1234567

转义

import re

content = "price is $5.00"
result = re.match("price is $5.00",content)
print(result)#特殊字符
result_ = re.match("price is \$5\.00",content)
print(result_)
None
<_sre.SRE_Match object; span=(0, 14), match='price is $5.00'>

总结:尽量使用泛匹配,使用括号得到匹配目标,尽量使用非贪婪模式,有换行符就用re.$

re.search

re.search 扫描整个字符串并返回第一个成功的匹配。

import re

content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
result = re.match('He.*?(\d+).*Demo',content)
print(result)#re.match 必须限定头部
None
import re

content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
result = re.search('He.*?(\d+).*Demo',content)
print(result)
print(result.group(1))

总结:为匹配方便,能用search就不用match

匹配演练

import re
html = """ <div id="songs-list">
           <h2 class="title">经典老歌</h2>
           <p class="introduction">
            经典老歌列表
           </p>
           <ul id="list" class="list-group">
            <li data-view="2">一路上有你</li>
            <li data-view="7">
              <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
            </li> 
            <li data-view="4" class="active"> 
                <a href="/3.mp3" singer="齐秦">往事随风</a> 
            </li> 
            <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li> 
            <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li> 
            <li data-view="5"> 
               <a href="/6.mp3" singer="邓丽君">但愿人长久</a> 
            </li> 
            </ul> 
            </div> """
result = re.search('<li.*?active.*?singer="(.*?)">(.*?)</a>',html,re.S)
if result:
    print(result.group(1),result.group(2))
齐秦 往事随风
import re
html = """ <div id="songs-list">
           <h2 class="title">经典老歌</h2>
           <p class="introduction">
            经典老歌列表
           </p>
           <ul id="list" class="list-group">
            <li data-view="2">一路上有你</li>
            <li data-view="7">
              <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
            </li> 
            <li data-view="4" class="active"> 
                <a href="/3.mp3" singer="齐秦">往事随风</a> 
            </li> 
            <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li> 
            <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li> 
            <li data-view="5"> 
               <a href="/6.mp3" singer="邓丽君">但愿人长久</a> 
            </li> 
            </ul> 
            </div> """
result = re.search('<li.*?singer="(.*?)">(.*?)</a>',html)
if result:
    print(result.group(1),result.group(2))#把re.S去掉后无法识别换行符
beyond 光辉岁月

re.findall

搜索字符串,以列表形式返回全部能匹配的字串

import re
html = """ <div id="songs-list">
           <h2 class="title">经典老歌</h2>
           <p class="introduction">
            经典老歌列表
           </p>
           <ul id="list" class="list-group">
            <li data-view="2">一路上有你</li>
            <li data-view="7">
              <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
            </li> 
            <li data-view="4" class="active"> 
                <a href="/3.mp3" singer="齐秦">往事随风</a> 
            </li> 
            <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li> 
            <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li> 
            <li data-view="5"> 
               <a href="/6.mp3" singer="邓丽君">但愿人长久</a> 
            </li> 
            </ul> 
            </div> """
results = re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>',html,re.S)
print(results)
print(type(results))
for result in results:
    print(result)
    print(result[0],result[1],result[2])
[('/2.mp3', '任贤齐', '沧海一声笑'), ('/3.mp3', '齐秦', '往事随风'), ('/4.mp3', 'beyond', '光辉岁月'), ('/5.mp3', '陈慧琳', '记事本'), ('/6.mp3', '邓丽君', '但愿人长久')]
<class 'list'>
('/2.mp3', '任贤齐', '沧海一声笑')
/2.mp3 任贤齐 沧海一声笑
('/3.mp3', '齐秦', '往事随风')
/3.mp3 齐秦 往事随风
('/4.mp3', 'beyond', '光辉岁月')
/4.mp3 beyond 光辉岁月
('/5.mp3', '陈慧琳', '记事本')
/5.mp3 陈慧琳 记事本
('/6.mp3', '邓丽君', '但愿人长久')
/6.mp3 邓丽君 但愿人长久
import re
html = """ <div id="songs-list">
           <h2 class="title">经典老歌</h2>
           <p class="introduction">
            经典老歌列表
           </p>
           <ul id="list" class="list-group">
            <li data-view="2">一路上有你</li>
            <li data-view="7">
              <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
            </li> 
            <li data-view="4" class="active"> 
                <a href="/3.mp3" singer="齐秦">往事随风</a> 
            </li> 
            <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li> 
            <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li> 
            <li data-view="5"> 
               <a href="/6.mp3" singer="邓丽君">但愿人长久</a> 
            </li> 
            </ul> 
            </div> """
results = re.findall('<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>',html,re.S)
print(results)
for result in results:
    print(result[1])
[('', '一路上有你', ''), ('<a href="/2.mp3" singer="任贤齐">', '沧海一声笑', '</a>'), ('<a href="/3.mp3" singer="齐秦">', '往事随风', '</a>'), ('<a href="/4.mp3" singer="beyond">', '光辉岁月', '</a>'), ('<a href="/5.mp3" singer="陈慧琳">', '记事本', '</a>'), ('<a href="/6.mp3" singer="邓丽君">', '但愿人长久', '</a>')]
一路上有你
沧海一声笑
往事随风
光辉岁月
记事本
但愿人长久

re.sub

替换字符串每一个匹配的子串后返回替换后的字符串。

import re

content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
content = re.sub('\d+','',content)
print(content)
Extra stings Hello  World_This is a Regex Demo Extra stings
import re

content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
content = re.sub('(\d+)','Replacement',content)
print(content)
Extra stings Hello Replacement World_This is a Regex Demo Extra stings
import re

content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
content = re.sub('(\d+)',r'\1 8910',content)
print(content)
Extra stings Hello 1234567 8910 World_This is a Regex Demo Extra stings
import re
html = """ <div id="songs-list">
           <h2 class="title">经典老歌</h2>
           <p class="introduction">
            经典老歌列表
           </p>
           <ul id="list" class="list-group">
            <li data-view="2">一路上有你</li>
            <li data-view="7">
              <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
            </li> 
            <li data-view="4" class="active"> 
                <a href="/3.mp3" singer="齐秦">往事随风</a> 
            </li> 
            <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li> 
            <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li> 
            <li data-view="5"> 
               <a href="/6.mp3" singer="邓丽君">但愿人长久</a> 
            </li> 
            </ul> 
            </div> """
html = re.sub('<a.*?>|</a>','',html)
print(html)
results = re.findall('<li.*?>(.*?)</li>',html,re.S)
print(results)
for result in results:
    print(result.strip())

re.compile

将正则字符串编译成正则表达式对象

将一个正则表达式串编译成正则对象,以便于复用该匹配模式

import re

content = "Hello 1234567 World_This is a Regex Demo"
pattern = re.compile('Hello.*Demo',re.S)
result = re.match(pattern,content)
#result = re.match('Hello.*Demo',content,re.S)
print(result)
<_sre.SRE_Match object; span=(0, 40), match='Hello 1234567 World_This is a Regex Demo'>

实战练习

import requests
import re
content = requests.get('https://book.douban.com').text
pattern = re.compile('<li.*?cover.*?href="(.*?)".*?title="(.*?)".*?more-meta.*?author">(.*?)</span>.*?year">(.*?)</span>.*?</li>',re.S)
results = re.findall(pattern,content)
for result in results:
    url,name,author,data = result
    author = re.sub('\s','',author)
    date = re.sub('\s','',date)
    print(url,name,author,date)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值