什么是正则表达式

正则表达式,又称规则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本。

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

给定一个正则表达式和另一个字符串,我们可以达到如下的目的:

给定的字符串是否符合正则表达式的过滤逻辑(“匹配”);

通过正则表达式,从文本字符串中获取我们想要的特定部分(“过滤”)。

常用的匹配规则:

  1. \w 匹配字母数字及下划线
  2. \W 匹配f非字母数字下划线
  3. \s 匹配任意空白字符,等价于[\t\n\r\f]
  4. \S 匹配任意非空字符
  5. \d 匹配任意数字
  6. \D 匹配任意非数字
  7. \A 匹配字符串开始
  8. \Z 匹配字符串结束,如果存在换行,只匹配换行前的结束字符串
  9. \z 匹配字符串结束
  10. \G 匹配最后匹配完成的位置
  11. \n 匹配一个换行符
  12. \t 匹配一个制表符
  13. ^ 匹配字符串的开头
  14. $ 匹配字符串的末尾
  15. . 匹配任意字符,除了换行符,re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符
  16. [....] 用来表示一组字符,单独列出:[amk]匹配a,mk
  17. [^...] 不在[]中的字符:[^abc]匹配除了a,b,c之外的字符
  18. * 匹配0个或多个的表达式
  19. + 匹配1个或者多个的表达式
  20. ? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
  21. {n} 精确匹配n前面的表示
  22. {m,m} 匹配nm次由前面的正则表达式定义片段,贪婪模式
  23. a|b 匹配a或者b
  24. () 匹配括号内的表达式,也表示一个组

Python 的 re 模块

在 Python 中,我们可以使用内置的 re 模块来使用正则表达式。

有一点需要特别注意的是,正则表达式使用 对特殊字符进行转义,所以如果我们要使用原始字符串,只需加一个 r 前缀。

re 模块的一般使用步骤如下:

1、使用 compile() 函数将正则表达式的字符串形式编译为一个 Pattern 对象

    compile 函数

  compile 函数用于编译正则表达式,生成一个 Pattern 对象,它的一般使用形式如下:

  1. import re
  2.  
  3. # 将正则表达式编译成 Pattern 对象
  4. pattern = re.compile(r'\d+') 

    在上面,我们已将一个正则表达式编译成 Pattern 对象,接下来,我们就可以利用 pattern 的一系列方法对文本进行匹配查找了。

  Pattern 对象的一些常用方法主要有:

  • match 方法:从起始位置开始查找,一次匹配
  • search 方法:从任何位置开始查找,一次匹配
  • findall 方法:全部匹配,返回列表
  • finditer 方法:全部匹配,返回迭代器
  • split 方法:分割字符串,返回列表
  • sub 方法:替换

2、通过 Pattern 对象提供的一系列方法对文本进行匹配查找,获得匹配结果,一个 Match 对象。

  2.1、match 方法

match 方法用于查找字符串的头部(也可以指定起始位置),它是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果。它的一般使用形式如下:

  match(string[, pos[, endpos]])

    其中,string 是待匹配的字符串,pos 和 endpos 是可选参数,指定字符串的起始和终点位置,默认值分别是 0 和 len (字符串长度)。因此,当你不指定 pos 和 endpos   时,match 方法默认匹配字符串的头部。

    当匹配成功时,返回一个 Match 对象,如果没有匹配上,则返回 None。

  

  1. >>> import re
  2. >>> pattern = re.compile(r'\d+') # 用于匹配至少一个数字
  3.  
  4. >>> m = pattern.match('one12twothree34four') # 查找头部,没有匹配
  5. >>> print m
  6. None
  7.  
  8. >>> m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配
  9. >>> print m
  10. None
  11.  
  12. >>> m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配
  13. >>> print m # 返回一个 Match 对象
  14. <_sre.SRE_Match object at 0x10a42aac0>
  15.  
  16. >>> m.group(0) # 可省略 0
  17. ''
  18. >>> m.start(0) # 可省略 0
  19. 3
  20. >>> m.end(0) # 可省略 0
  21. 5
  22. >>> m.span(0) # 可省略 0
  23. (3, 5)

  

  在上面,当匹配成功时返回一个 Match 对象,其中:

    group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);

    start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;

    end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;

    span([group]) 方法返回 (start(group), end(group))。

  2.2、search 方法

    search 方法用于查找字符串的任何位置,它也是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果,它的一般使用形式如下:

    search(string[, pos[, endpos]])

      其中,string 是待匹配的字符串,pos 和 endpos 是可选参数,指定字符串的起始和终点位置,默认值分别是 0 和 len (字符串长度)。

    当匹配成功时,返回一个 Match 对象,如果没有匹配上,则返回 None。

      让我们看看例子:    

  1. import re
  2. # 将正则表达式编译成 Pattern 对象
  3. pattern = re.compile(r'\d+')
  4. # 使用 search() 查找匹配的子串,不存在匹配的子串时将返回 None
  5. # 这里使用 match() 无法成功匹配
  6. m = pattern.search('hello 123456 789')
  7. if m:
  8. # 使用 Match 获得分组信息
  9. print'matching string:',m.group())
  10. # 起始位置和结束位置
  11. print'position:',m.span())
  12.  
  13. #结果
  14. matching string: 123456
  15. position: (6, 12)

  2.3、findall 方法

    上面的 match 和 search 方法都是一次匹配,只要找到了一个匹配的结果就返回。然而,在大多数时候,我们需要搜索整个字符串,获得所有匹配的结果。

    findall 方法的使用形式如下:

    findall(string[, pos[, endpos]])

      其中,string 是待匹配的字符串,pos 和 endpos 是可选参数,指定字符串的起始和终点位置,默认值分别是 0 和 len (字符串长度)。

      findall 以列表形式返回全部能匹配的子串,如果没有匹配,则返回一个空列表。

      看看例子:

  1. import re
  2.  
  3. #re模块提供一个方法叫compile模块,提供我们输入一个匹配的规则
  4. #然后返回一个pattern实例,我们根据这个规则去匹配字符串
  5. pattern = re.compile(r'\d+.\d*')
  6.  
  7. #通过partten.findall()方法就能够全部匹配到我们得到的字符串
  8. result = pattern.findall("123.141593, 'bigcat', 232312, 3.15")
  9.  
  10. #findall 以 列表形式 返回全部能匹配的子串给result
  11. for item in result:
  12. print(item)
  13.  
  14. #结果
  15. 123.141593
  16. 232312,
  17. 3.15

  2.4、finditer 方法

    finditer 方法的行为跟 findall 的行为类似,也是搜索整个字符串,获得所有匹配的结果。但它返回一个顺序访问每一个匹配结果(Match 对象)的迭代器。

  2.5、sub 方法

    sub 方法用于替换。它的使用形式如下:

    sub(repl, string[, count])

    其中,repl 可以是字符串也可以是一个函数:

      如果 repl 是字符串,则会使用 repl 去替换字符串每一个匹配的子串,并返回替换后的字符串,另外,repl 还可以使用 id 的形式来引用分组,但不能使用编号 0;

      如果 repl 是函数,这个方法应当只接受一个参数(Match 对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。

      count 用于指定最多替换次数,不指定时全部替换。

    看看例子:

  1. import re
  2. p = re.compile(r'(\w+) (\w+)') # \w = [A-Za-z0-9]
  3. s = 'hello 123, hello 456'
  4.  
  5. print(p.sub(r'hello world', s)) # 使用 'hello world' 替换 'hello 123' 和 'hello 456'
  6. print(p.sub(r'\2 \1', s)) # 引用分组
  7.  
  8. def func(m):
  9. return 'hi' + ' ' + m.group(2)
  10.  
  11. print(p.sub(func, s))
  12. print(p.sub(func, s, 1)) # 最多替换一次
  13.  
  14. #结果
  15. hello world, hello world
  16. 123 hello, 456 hello
  17. hi 123, hi 456
  18. hi 123, hello 456

3、最后使用 Match 对象提供的属性和方法获得信息,根据需要进行其他的操作

也可以直接用re.match(),re.search(),re.findall(),re.finditer(),re.sub()

  1. import re
  2. content= "hello 1234567 World_This is a regex Demo"
  3. result = re.match('^hello\s(\d+)\sWorld.*Demo$',content)
  4. print(result)
  5. print(result.group())
  6. print(result.group(1))
  7. print(result.span())

结果:

  1. <_sre.SRE_Match object; span=(0, 40), match='hello 1234567 World_This is a regex Demo'>
  2. hello 1234567 World_This is a regex Demo
  3. 1234567
  4. (0, 40)

使用正则表达式的爬虫:(小说)

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3.  
  4. import urllib.request
  5. import re
  6.  
  7. class Spider:
  8. def __init__(self):
  9. # 初始化起始页位置
  10. self.page = 1
  11. # 爬取开关,如果为True继续爬取
  12. self.switch = True
  13.  
  14. def loadPage(self):
  15. """
  16. 作用:下载页面
  17. """
  18. print("正在下载数据....")
  19. url = "https://www.siluke.tw/ny10345/" + str(self.page+6059038) + ".html"
  20. headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
  21. request = urllib.request.Request(url, headers = headers)
  22. response = urllib.request.urlopen(request)
  23.  
  24. # 获取每页的HTML源码字符串
  25. html = response.read().decode('utf-8')
  26. #print html
  27.  
  28. # 创建正则表达式规则对象,匹配每页里的段子内容,re.S 表示匹配全部字符串内容
  29. #pattern = re.compile('<div\sclass="f18 mb20">(.*?)</div>', re.S)
  30. pattern = re.compile('<div\sid="content">(.*?)</div>')
  31.  
  32. # 将正则匹配对象应用到html源码字符串里,返回这个页面里的所有文章的列表
  33. content_list = pattern.findall(html)
  34.  
  35. # 调用dealPage() 处理文章里的杂七杂八
  36. self.dealPage(content_list)
  37.  
  38. def dealPage(self, content_list):
  39. """
  40. 处理每页的文章
  41. content_list : 每页的文章列表集合
  42. """
  43. for item in content_list:
  44. # 将集合里的每个段子按个处理,替换掉无用数据
  45. item = item.replace('<br />', '').replace('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;','').replace('&nbsp;&nbsp;&nbsp;&nbsp;', '\n').replace('&nbsp;...&nbsp;&nbsp;','\n')
  46.  
  47. # 处理完后调用writePage() 将每个段子写入文件内
  48. self.writePage(item)
  49.  
  50. def writePage(self, item):
  51. """
  52. 把每章逐个写入文件里
  53. item: 处理后的文章
  54. """
  55. # 写入文件内
  56. print("正在写入数据....")
  57. with open("斗破苍穹.txt", "a") as f:
  58. f.write('第%s章\n' % self.page)
  59. f.write('\n')
  60. f.write(item)
  61. f.write('\n')
  62.  
  63. def startWork(self):
  64. """
  65. 控制爬虫运行
  66. """
  67. # 循环执行,直到 self.switch == False
  68. while self.switch:
  69. # 用户确定爬取的次数
  70. self.loadPage()
  71. command = input("如果继续爬取,请按回车(退出输入quit)")
  72. if command == "quit":
  73. # 如果停止爬取,则输入 quit
  74. self.switch = False
  75. # 每次循环,page页码自增1
  76. self.page += 1
  77. print("谢谢使用!")
  78.  
  79. if __name__ == "__main__":
  80. articleSpider = Spider()
  81. # articleSpider.loadPage()
  82. articleSpider.startWork()

运行结果:

  1. 正在下载数据....
  2. 正在写入数据....
  3. 如果继续爬取,请按回车(退出输入quit)quit
  4. 谢谢使用!

四、正则表达式re模块的更多相关文章

  1. python 正则表达式re模块

    #####################总结##############    优点:  灵活, 功能性强, 逻辑性强.               缺点:  上手难,旦上手, 会爱上这个东西    ...

  2. python基础之正则表达式 re模块

    内容梗概: 1. 正则表达式 2. re模块的使⽤ 3. 一堆练习正则表达式是对字符串串操作的一种逻辑公式. 我们一般使用正则表达式对字符串进行匹配和过滤.使用正则的优缺点: 优点: 灵活,功能性强, ...

  3. python记录_day23 正则表达式 re模块

    一. 正则表达式 使用python的re模块之前应该对正则表达式有一定的了解 正则表达式是对字符串操作的一种逻辑公式.我们一般使用正则表达式对字符串进行匹配和过滤. 正则的优缺点: 优点:灵活, 功能 ...

  4. Python面试题之Python正则表达式re模块

    一.Python正则表达式re模块简介 正则表达式,是一门相对通用的语言.简单说就是:用一系列的规则语法,去匹配,查找,替换等操作字符串,以达到对应的目的:此套规则,就是所谓的正则表达式.各个语言都有 ...

  5. 044医疗项目-模块四:采购单模块—采购单保存(Dao,Service,Action三层)

    我们上上一篇文章(042医疗项目-模块四:采购单模块-采购单明细添加查询,并且把数据添加到数据库中)做的工作是把数据插入到了数据库,我们这篇文章做的是042医疗项目-模块四:采购单模块-采购单明细添加 ...

  6. Python第二十四天 binascii模块

    Python第二十四天 binascii模块 binascii用来进行进制和字符串之间的转换 import binascii s = 'abcde' h = binascii.b2a_hex(s) # ...

  7. AngularJS进阶(四十)创建模块、服务

    AngularJS进阶(四十)创建模块.服务 学习要点 使用模块构架应用 创建和使用服务 为什么要使用和创建服务与模块? 服务允许你打包可重用的功能,使之能在此应用中使用. 模块允许你打包可重用的功能 ...

  8. python正则表达式Re模块备忘录

    title: python正则表达式Re模块备忘录 date: 2019/1/31 18:17:08 toc: true --- python正则表达式Re模块备忘录 备忘录 python中的数量词为 ...

  9. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验四:按键模块③ — 单击与双击

    实验四:按键模块③ - 单击与双击 实验三我们创建了"点击"还有"长点击"等有效按键的多功能按键模块.在此,实验四同样也是创建多功能按键模块,不过却有不同的有效 ...

  10. spring cloud: zuul(四): 正则表达式匹配其他微服务(给其他微服务加版本号)

    spring cloud: zuul(四): 正则表达式匹配其他微服务(给其他微服务加版本号) 比如我原来有,spring-boot-user微服务,后台进行迭代更新,另外其了一个微服务: sprin ...

随机推荐

  1. jquery1.8 在IE8 下面报错:对象不支持此属性或方法 return b.getAttribute("id")===a

    jquery1.8 在IE8 下面报错: 对象不支持此属性或方法 调试发现是下面这一行报错: 在IE8下面报错,在chrome和firefox都是好的. 实在找不到原因,最后把源码改成下面这样: 没有 ...

  2. chorme调试Paused in debugger问题解决

    最近出现的问题,使用chorme调试代码总是这个状态(Paused in debugger[debug的时候暂停了]): 一刷新就这样,非常的不舒服.当然你可以选择多按几次F8跳出,下面提供几种方式解 ...

  3. Spark算子--take、top、takeOrdered

    转载请标明出处http://www.cnblogs.com/haozhengfei/p/552e8a32eee9d50fe394dfdcb14c78f3.html take.top.takeOrder ...

  4. VN问题:error:请求的名称有效,但是找不到请求的类型的

    把url中的jmsjms-pc换成IP地址试试看 IP地址你用的是外网地址,应该用局域网内网地址,改成内网地址再试试看 还有练习架设SVN服务器初期尽量用http协议,不要上来就用https协议,ht ...

  5. wamp apache无法启动的解决方法

    作者 grunmin 2014.03.12 14:44* 字数 535 阅读 22167评论 9喜欢 5 如题,近日在安装wamp的时候出现了apache无法启动的情况.wamp图标一直显示橙色.网上 ...

  6. Spring @Scheduled 在tomcat容器里面执行两次

    今天在用spring里面的@Scheduled执行定时任务,但是发现到触发定时任务的时间点总会执行两次.原因是修改了tomcat conf包下面的server.xml文件导致的.配置如下: <H ...

  7. P2045 方格取数加强版

    P2045 方格取数加强版 题目描述 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格 ...

  8. python初识 - day4

    一.集合(set) 1.集合的定义 set 是一个无序的元素集合,支持并.交.差及对称差等数学运算, 但由于 set 不记录元素位置, 因此不支持索引.分片等类序列的操作. 2.集合的创建 大括号或 ...

  9. JAVA中比较两个文件夹不同的方法

    JAVA中比较两个文件夹不同的方法,可以通过两步来完成,首先遍历获取到文件夹下的所有文件夹和文件,再通过文件路径和文件的MD5值来判断文件的异同.具体例子如下: public class TestFo ...

  10. JAVA中正则表达式常用的四个方法

    JAVA中正则表达式处理字符串的四个常用方法:匹配.分割.替换.截取.其跟字符串的常用函数相似,但是使用正则表达式会更简单.更加简洁.下面是具体的例子: public class TestRegex ...