当给你一大堆文本信息,让你提取其中的指定数据时,可以使用正则来实现。

  1. # 例如:提取文本中的邮箱
  2. import re
  3. text = "楼主太牛逼了一giao我里giao,在线想要 598779784@qq.com,搞起来呀"
  4. phone_list = re.findall("\d{4,9}@qq.com", text)
  5. print(phone_list) # ['598779784@qq.com']

正则语法

常用元字符

  1. .匹配除换行符以外的任意字符
  2. ^匹配字符串的开始(多行情况下匹配每一行的开头)
  3. $匹配字符串的结束(多行情况下匹配每一行的开头)
  4. \b匹配单词的开始或结束
  5. \d匹配一个数字 相当于[0-9]
  6. \s匹配一个空格(也包括Tab等空白符)相当于[\t\n\r\f\v]
  7. \w匹配一个字母或数字 [a-zA-Z0-9]
  8. \A 仅匹配字符串的开头,类似 ^, 但不处理多行
  9. \B 匹配不是单词开头或结束的位置
  10. \D 匹配任意非数字的字符 相当于[^0-9]
  11. \S 匹配任意不是空白符的字符 [^\t\n\r\f\v]
  12. \W 匹配任意不是字母,数字,下划线,汉字的字符 [^a-zA-Z0-9]
  13. [^x] 匹配除了x以外的任意字符
  14. [^abcdef] 匹配除了abcdef这几个字母以外的任意字符
  15. \Z 仅匹配字符串的结尾,类似 $, 但不处理多行

常用限定符

  1. * 重复零次或更多次
  2. + 重复一次或更多次
  3. ? 重复零次或一次
  4. {n} 重复n
  5. {n,} 重复n次或更多次
  6. {m,n} 重复mn

贪婪与懒惰

(正则匹配默认是贪婪匹配,加个?就可以非贪婪匹配)

  1. *? 重复任意次,但尽可能少重复
  2. +? 重复1次或更多次,但尽可能少重复
  3. ?? 重复0次或1次,但尽可能少重复
  4. {n,m}? 重复nm次,但尽可能少重复
  5. {n,}? 重复n次以上,但尽可能少重复

字符转义

  1. \ 来取消这些字符的特殊意义
  2. \\ \
  3. \. .
  4. \* *

分组

  1. (?P<name>...) 通过group方法访问
  2. 符号:.、^、$、*、+、?、{}、[]、\、|、()
  3. 文件名匹配:?代表一个字符,*代表多个字符

re模块

python中提供了re模块,可以处理正则表达式并对文本进行处理。

常用方法

  • findall,获取匹配到的所有数据 ```python import re

text = “dsf130429191912015219k13042919591219521Xkk” data_list = re.findall(“(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)”, text) print(data_list) # [(‘130429’, ‘1919’, ‘12’, ‘01’, ‘521’, ‘9’), (‘130429’, ‘1959’, ‘12’, ‘19’, ‘521’, ‘X’)]

  1. - match,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None
  2. ```python
  3. import re
  4. text = "大小逗2B最逗3B欢乐"
  5. data = re.match("逗\dB", text)
  6. print(data) # None
  1. import re
  2. text = "逗2B最逗3B欢乐"
  3. data = re.match("逗\dB", text)
  4. if data:
  5. content = data.group() # "逗2B"
  6. print(content)
  • search,浏览整个字符串去匹配第一个,未匹配成功返回None ```python import re

text = “大小逗2B最逗3B欢乐” data = re.search(“逗\dB”, text) if data: print(data.group()) # “逗2B”

  1. - sub,替换匹配成功的位置
  2. ```python
  3. import re
  4. text = "逗2B最逗3B欢乐"
  5. data = re.sub("\dB", "沙雕", text)
  6. print(data) # 逗沙雕最逗沙雕欢乐
  1. import re
  2. text = "逗2B最逗3B欢乐"
  3. data = re.sub("\dB", "沙雕", text, 1)
  4. print(data) # 逗沙雕最逗3B欢乐
  • split,根据匹配成功的位置分割 ```python import re

text = “逗2B最逗3B欢乐” data = re.split(“\dB”, text) print(data) # [‘逗’, ‘最逗’, ‘欢乐’]

  1. ```python
  2. import re
  3. text = "逗2B最逗3B欢乐"
  4. data = re.split("\dB", text, 1)
  5. print(data) # ['逗', '最逗3B欢乐']
  • finditer

python正则模块re中findall和finditer两者相似,但却有很大区别。
两者都可以获取所有的匹配结果,这和findall方法有着很大的区别,同时不同的是一个返回list,一个返回一个MatchObject类型的iterator

  1. import re
  2. text = "逗2B最逗3B欢乐"
  3. data = re.finditer("\dB", text)
  4. for item in data:
  5. print(item.group())
  1. # 有名分组
  2. import re
  3. text = "逗2B最逗3B欢乐"
  4. data = re.finditer("(?P<xx>\dB)", text) # 命名分组
  5. for item in data:
  6. print(item.groupdict())
  7. # {'xx': '2B'}
  8. # {'xx': '3B'}
  1. import re
  2. text = "dsf130429191912015219k13042919591219521Xkk"
  3. data_list = re.finditer("\d{6}(?P<year>\d{4})(?P<month>\d{2})(?P<day>\d{2})\d{3}[\d|X]", text)
  4. for item in data_list:
  5. info_dict = item.groupdict()
  6. print(info_dict)
  7. # {'year': '1919', 'month': '12', 'day': '01'}
  8. # {'year': '1959', 'month': '12', 'day': '19'}

【标志位】

使用较少,
第三个参数,默认flags=0

  1. re.DEBUG re.M re.U re.error re.search re.sys
  2. re.DOTALL re.MULTILINE re.UNICODE re.escape re.split re.template
  3. re.I re.S re.VERBOSE re.findall re.sre_compile
  4. re.IGNORECASE re.Scanner re.X re.finditer re.sre_parse
  5. re.L re.T re.compile re.match re.sub
  6. re.LOCALE re.TEMPLATE re.copy_reg re.purge re.subn

re.M //识别\n,将一个字符串按\n分成多个

  1. In [1]: import re
  2. In [2]: data = 'foo1\nfoo2\n'
  3. In [3]: re.findall(r'foo.$',data)
  4. Out[3]: ['foo2']
  5. In [4]: re.findall(r'foo.$',data,re.M)
  6. Out[4]: ['foo1', 'foo2']

compile语法

可以把正则语法单独拿出来

  1. import re
  2. text = "逗2B最逗3B欢乐"
  3. re_text = re.compile('\dB', re.M)
  4. data = re.sub(re_text, "沙雕", text)
  5. print(data) # 逗沙雕最逗沙雕欢乐

实战一

1. 字符相关

  • mufeng 匹配文本中的mufeng ```python import re

text = “你好mufeng,阿斯顿发wupeiqasd 阿士大夫能接受的mufengff” data_list = re.findall(“mufeng”, text) print(data_list) # [‘mufeng’, ‘mufeng’] 可用于计算字符串中某个字符出现的次数

  1. - `[abc]` 匹配abc 字符。
  2. ```python
  3. import re
  4. text = "你好mufeng,阿斯顿发wupeiqasd 阿士大夫能接受的bbupqaceiqiff"
  5. data_list = re.findall("[abc]", text)
  6. print(data_list) # ['a', 'b', 'b', 'a', 'c']
  1. import re
  2. text = "你好mufeng,阿斯顿发wupeiqasd 阿士大夫能接受的bbupqaceiqiff"
  3. data_list = re.findall("q[abc]", text)
  4. print(data_list) # ['qa', 'qa']
  • [^abc] 匹配除了abc意外的其他字符。 ```python import re

text = “你好mufeng,bbupqaceiqiff”

data_list = re.findall(“[^abcdef]”, text) print(data_list)

[‘你’, ‘好’, ‘m’, ‘u’, ‘n’, ‘g’, ‘,’, ‘u’, ‘p’, ‘q’, ‘i’, ‘q’, ‘i’]

  1. - `[a-z]` 匹配a~z的任意字符( [0-9]也可以 )。
  2. ```python
  3. import re
  4. text = "mufengrootrootadmin"
  5. data_list = re.findall("t[a-z]", text)
  6. print(data_list) # ['tr', 'ta']
  • . 代指除换行符以外的任意字符。 ```python import re

text = “mufengrootrootadmin” data_list = re.findall(“r.o”, text) print(data_list) # [‘rao’, ‘roo’]

  1. ```python
  2. import re
  3. text = "mufengrootrootadmin"
  4. data_list = re.findall("r.+o", text) # 贪婪匹配
  5. print(data_list) # ['raotroo']
  • \w 代指字母或数字或下划线(汉字)。 ```python import re

text = “北京沐风ecithy 江苏沐风deepwind” data_list = re.findall(“沐风\w+”, text) print(data_list) # [‘沐风ecithy’, ‘沐风deepwind’]

  1. - `\d` 代指数字
  2. ```python
  3. import re
  4. text = "root-ad32min-add3-admd1in"
  5. data_list = re.findall("d\d", text)
  6. print(data_list) # ['d3', 'd3', 'd1']
  • \s 代指任意的空白符,包括空格、制表符等。 ```python import re

text = “root admin add admin” data_list = re.findall(“a\w+\s\w+”, text) print(data_list) # [‘admin add’]

  1. <a name="GALJt"></a>
  2. ### 2. 数量相关
  3. - `*` 重复0次或更多次
  4. ```python
  5. import re
  6. text = "他是大B个,确实是个大2B。"
  7. data_list = re.findall("大2*B", text)
  8. print(data_list) # ['大B', '大2B']
  • + 重复1次或更多次 ```python import re

text = “他是大B个,确实是个大2B,大3B,大66666B。” data_list = re.findall(“大\d+B”, text) print(data_list) # [‘大2B’, ‘大3B’, ‘大66666B’]

  1. - `?` 重复0次或1
  2. ```python
  3. import re
  4. text = "他是大B个,确实是个大2B,大3B,大66666B。"
  5. data_list = re.findall("大\d?B", text)
  6. print(data_list) # ['大B', '大2B', '大3B']
  • {n} 重复n次
  1. import re
  2. text = "楼主太牛逼了,在线想要 598779784@qq.com和xxxxx@live.com谢谢楼主,手机号也可18879404697,搞起来呀"
  3. data_list = re.findall("188794\d{5}", text)
  4. print(data_list) # ['15131255789']
  • {n,} 重复n次或更多次 ```python import re

text = “楼主太牛逼了,在线想要 598779784@qq.com和xxxxx@live.com谢谢楼主,手机号也可18879404697,搞起来呀” data_list = re.findall(“188794\d{3,}”, text) print(data_list) # [‘18879404697’]

  1. - `{n,m}` 重复nm
  2. ```python
  3. import re
  4. text = "楼主太牛逼了,在线想要 598779784@qq.com和xxxxx@live.com谢谢楼主,手机号也可18879404697,搞起来呀"
  5. data_list = re.findall("188794\d{3,9}", text)
  6. print(data_list) # ['18879404697']

3. 括号(分组)

  • 提取数据区域 ```python import re

text = “楼主太牛逼了,在线想要 598779784@qq.com和xxxxx@live.com谢谢楼主,手机号也可18879404697,搞起来呀” data_list = re.findall(“188(79\d{5,})”, text) print(data_list) # [‘79404697’]

  1. ```python
  2. import re
  3. text = "楼主太牛逼了,在线想要 598779784@qq.com和xxxxx@live.com谢谢楼主,手机号也可18879404697,搞起来呀"
  4. data_list = re.findall("188(79)(\d{5,})", text)
  5. print(data_list) # [('79', '404697')]
  • 获取指定区域 + 或条件 ```python import re

text = “楼主太牛逼了,在线想要 598779784@qq.com和xxxxx@live.com谢谢楼主,手机号也可18879404697,搞起来呀” data_list = re.findall(“(\d{5,}|\w{3})@\w+?.com”, text) print(data_list) # [‘598779784’, ‘xxx’]

  1. <a name="KNXx1"></a>
  2. ### 4. 起始和结束
  3. 上述示例中都是去一段文本中提取数据,只要文本中存在即可。<br />但,如果要求用户输入的内容必须是指定的内容开头和结尾,比就需要用到如下两个字符。<br />这种一般用于对用户输入数据格式的校验比较多,例如:
  4. ```python
  5. import re
  6. text = "598779784@qq.com"
  7. email_list = re.findall("^\w+@\w+.\w+$", text, re.ASCII)
  8. print(email_list) # []

实战二

QQ

  1. import re
  2. text = "我的企鹅号是598779784, 小号是649848996964"
  3. data_list = re.findall("[1-9]\d{4,}", text)
  4. print(data_list) # ['598779784', '649848996964']

手机号

  1. import re
  2. text = "我的手机号是18879404697, 小号是16679404698"
  3. data_list = re.findall("\d{11}", text)
  4. print(data_list) # ['18879404697', '16679404698']

邮箱地址

  1. import re
  2. # 汉字范围: [\u4E00-\u9FA5]
  3. text = "我的手机号是18879404697@126.com, 小号是598779784@qa.com"
  4. data_list = re.findall("[\u4E00-\u9FA5]+(\w+@\w+\.\w+)",text)
  5. print(data_list) # ['18879404697@126.com', '598779784@qa.com']