http://tool.oschina.net/regex 在线正则表达式测试

常用方法

^ 开头
$ 结尾
\s 空格
\d 数字
\d{5} 5个数字
\w 小写w 匹配字母+数字+下划线
\W 大写 W 匹配非字母、非数字、非下划线
. 匹配任意字符,除了换行符(但是在指定匹配模式 re.S的时候就可以)
* 匹配0-多个字符
+ 匹配一个或多个字符
\s*? 匹配一个可能有,可能没有的空白字符
\n 匹配一个换行符。等价于 \x0a 和 \cJ。

Jupyter Notebook

Jupyter Notebook

  1. pip install jupyter
  2. jupyter notebook 在命令行运行

    re.match

    尝试是字符串起始位置开始匹配的一个模式,如果匹配不成功,返回 None
    1. re.match(pattern,string,flags=0)

    最常规的匹配

    1. import re
    2. #引入正则表达式库
    3. content = 'Hello 123 4567 World_This is a Regex Demo'
    4. print(len(content))
    5. result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}.*Demo$',content)
    6. # 【第一个参数是正则表达式的规则】,【第二个参数是被匹配的内容】
    7. print(result)
    8. #打印匹配结果信息
    9. print(result.group())
    10. # group 表示只打印匹配出来的结果
    11. print(result.span())
    12. # 输出匹配结果的范围
    结果如下:
    正则表达式 - 图1

    泛匹配

    1. import re
    2. content = 'Hello 123 4567 World_This is a Regex Demo'
    3. print(len(content))
    4. result = re.match('^Hello.*Demo$',content)
    5. # 泛匹配,匹配 Hello Demo 中间的所有内容。
    6. print(result)
    7. print(result.group())
    8. print(result.span())
    结果和上面的是一样的。
    正则表达式 - 图2

    匹配目标

    1. import re
    2. content = 'Hello 1234567 World_This is a Regex Demo'
    3. result = re.match('^Hello\s(\d+)\sWorld.*Demo$',content)
    4. # 我们需要匹配的是1234567
    5. # \d+ 表示匹配1个或多个数字
    6. # () 内为需要匹配的内容
    7. print(result)
    8. print(result.group(1))
    9. # group(1)表示第一个group,如果匹配规则有两个group,那第二个就是 group(2)
    10. print(result.span())

    我们需要匹配的是1234567 \d+ 表示匹配1个或多个数字 () 内为需要匹配的内容 group(1)表示第一个group,如果匹配规则有两个group,那第二个就是 group(2)

贪婪模式

  1. import re
  2. content = 'Hello 1234567 World_This is a Regex Demo'
  3. result = re.match('^He.*(\d+).*Demo$',content)
  4. # .* 贪婪识别
  5. print(result)
  6. print(result.group(1))
  7. print(result.span())

结果如下,它只匹配到到了一个7, 因为(\d+)前面的 .*会匹配尽可能多的字符,而(\d+)是需要匹配至少一个,由于前面是贪婪的,所以(\d+)就只能得到一个数字了。
正则表达式 - 图3

非贪婪模式

.*后面加一个”问号”,变成 .*? 就是匹配 尽量少 的字符。

  1. import re
  2. content = 'Hello 1234567 World_This is a Regex Demo'
  3. result = re.match('^He.*?(\d+).*Demo$',content)
  4. # .*? 非贪婪识别
  5. print(result)
  6. print(result.group(1))
  7. print(result.span())

正则表达式 - 图4
这个时候结果就是1234567了 这个时候就让 (\d+) 尽量多的识别了字符

匹配模式(换行匹配)

  1. import re
  2. content = '''Hello 1234567 World_This
  3. is a Regex Demo'''
  4. # ''' 内容''' 是换行符的意思。如过按照上面的写法是无法匹配出结果的
  5. result = re.match('^He.*?(\d+).*Demo$',content,re.S)
  6. # 后面的re.S (大写 S)就可以让.匹配换行符了。
  7. print(result)
  8. print(result.group(1))
  9. print(result.span())

结果如下,在html里面有换行符是非常常见的。
正则表达式 - 图5

转义

  1. import re
  2. content = 'price is $5.00'
  3. result = re.match('price is \$5\.00',content)
  4. print(result)

在这里 $. 需要在前面加一个 \ 来把他们转义成字符串。 这样匹配出来的就没有问题。
正则表达式 - 图6

总结:

尽量使用泛匹配、使用括号的到匹配目标,尽量使用费贪婪模式,有换行符就用re.S

re.search

  1. import re
  2. content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
  3. result = re.match('Hello.*?(\d+).*?Demo',content)
  4. print(result)

我们从中间开始匹配,结果如下
正则表达式 - 图7
但是如果把 match 改成 search

  1. import re
  2. content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
  3. result = re.search('Hello.*?(\d+).*?Demo',content)
  4. # 把 match 改成 search
  5. print(result)

正则表达式 - 图8
这样就匹配成功了。

为了方便,能用search 就不用 match

匹配演练

  1. import re
  2. html = '''<div id="songs-list">
  3. <h2 class="title">经典老歌</h2>
  4. <p class="introduction">
  5. 经典老歌列表
  6. </p>
  7. <ul id="list" class="list-group">
  8. <li data-view="2">一路上有你</li>
  9. <li data-view="7">
  10. <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
  11. </li>
  12. <li data-view="4" class="active">
  13. <a href="/3.mp3" singer="齐秦">往事随风</a>
  14. </li>
  15. <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
  16. <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
  17. <li data-view="5">
  18. <a href="/6.mp3" singer="邓丽君">但愿人长久</a>
  19. </li>
  20. </ul>
  21. </div>'''
  22. result = re.search('<li.*active.*?singer="(.*?)">(.*?)</a>',html,re.S)
  23. if result: # 去掉也可以
  24. print(result.group(1),result.group(2))

结果如下,这里匹配的结果是 带 class= active 的标签,如果去掉 active 那就会匹配第一个

任贤齐 沧海一声笑

正则表达式 - 图9

re.findall

  1. import re
  2. html = '''<div id="songs-list">
  3. <h2 class="title">经典老歌</h2>
  4. <p class="introduction">
  5. 经典老歌列表
  6. </p>
  7. <ul id="list" class="list-group">
  8. <li data-view="2">一路上有你</li>
  9. <li data-view="7">
  10. <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
  11. </li>
  12. <li data-view="4" class="active">
  13. <a href="/3.mp3" singer="齐秦">往事随风</a>
  14. </li>
  15. <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
  16. <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
  17. <li data-view="5">
  18. <a href="/6.mp3" singer="邓丽君">但愿人长久</a>
  19. </li>
  20. </ul>
  21. </div>'''
  22. results = re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>',html,re.S)
  23. print(results)
  24. print(type(results))
  25. for result in results:
  26. print(result)
  27. print(result[0],result[1],result[2])

结果如下,匹配了所有的链接、歌手、歌名。
正则表达式 - 图10

匹配出歌词

  1. import re
  2. html = '''<div id="songs-list">
  3. <h2 class="title">经典老歌</h2>
  4. <p class="introduction">
  5. 经典老歌列表
  6. </p>
  7. <ul id="list" class="list-group">
  8. <li data-view="2">一路上有你</li>
  9. <li data-view="7">
  10. <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
  11. </li>
  12. <li data-view="4" class="active">
  13. <a href="/3.mp3" singer="齐秦">往事随风</a>
  14. </li>
  15. <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
  16. <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
  17. <li data-view="5">
  18. <a href="/6.mp3" singer="邓丽君">但愿人长久</a>
  19. </li>
  20. </ul>
  21. </div>'''
  22. results = re.findall('<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>',html,re.S)
  23. # 第一个()和最后一个括号是匹配<a></a>, 因为一路上有你没有a标签,所有后面加个 ? 表示可能为0-多个。
  24. # \s*? 表示0-多个空格
  25. #print(results)
  26. for result in results:
  27. print(result[1])

结果如下:
正则表达式 - 图11

re.sub

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

  1. import re
  2. content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
  3. content = re.sub('\d','q',content)
  4. #如果只写 \d 就会 1-7每个数字替换一次。qqqqqqq 效果如图1
  5. # 如果写成\d+ 就会把1234567 替换成 q 效果如图2
  6. # 第一个参数传入正则表达式,第二个参数传入要替换的内容,第三个参数传入元内容。
  7. print(content)

正则表达式 - 图12
正则表达式 - 图13

包括内容再替换

  1. import re
  2. content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
  3. content = re.sub('(\d+)',r'\1 q',content)
  4. # 需要把替换内容放在一个小括号内,需要替换的内容要 r'\1' r是声明一下,然后\1表示前面的括号内容,再添加其他内容 包括空格就会一起替换 之前的 1234567
  5. print(content)

正则表达式 - 图14

替换再findall

  1. import re
  2. html = '''<div id="songs-list">
  3. <h2 class="title">经典老歌</h2>
  4. <p class="introduction">
  5. 经典老歌列表
  6. </p>
  7. <ul id="list" class="list-group">
  8. <li data-view="2">一路上有你</li>
  9. <li data-view="7">
  10. <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
  11. </li>
  12. <li data-view="4" class="active">
  13. <a href="/3.mp3" singer="齐秦">往事随风</a>
  14. </li>
  15. <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
  16. <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
  17. <li data-view="5">
  18. <a href="/6.mp3" singer="邓丽君">但愿人长久</a>
  19. </li>
  20. </ul>
  21. </div>'''
  22. html = re.sub('<a.*?>|</a>','',html)
  23. #print(html)
  24. results = re.findall('<li.*?>(.*?)</li>', html, re.S)
  25. #print(results)
  26. for result in results:
  27. print(result.strip())
  28. #.strip()去掉换行符

结果如下
正则表达式 - 图15

re.compile

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

  1. import re
  2. content = '''Hello 1234567 World_This
  3. is a Regex Demo'''
  4. pattern = re.compile('Hello.*Demo',re.S)
  5. result = re.match(pattern,content)
  6. # 先写一个正则表达式规则并且赋予 pattern ,
  7. #下次就不用写正则表达式规则了,直接在规则那输入 pattern 就调用了这个正则表达式规则。
  8. #result = re.match('Hello.*Demo',content,re.S)
  9. #上面个语句表达出来的意思等同这次
  10. print(result)

实战练习

  1. import re
  2. import requests
  3. content = requests.get('https://book.douban.com/').text
  4. pattern = re.compile('<li.*?cover.*?href="(.*?)".*?title="(.*?)".*?more-meta.*?author">(.*?)</span>.*?year">(.*?)</span>.*?</li>', re.S)
  5. results = re.findall(pattern,content)
  6. #print(results)
  7. for result in results:
  8. url,name,author,date = result
  9. # 每个值是一个括号
  10. author = re.sub('\s','',author)
  11. date = re.sub('\s','',date)
  12. # author 和date 带换行符,取消掉
  13. print(url,name,author,date)
  14. #print(url,name,author.strip(),date.strip()) #等同于上面两行的效果

结果如下
正则表达式 - 图16