当给你一大堆文本信息,让你提取其中的指定数据时,可以使用正则来实现。
# 例如:提取文本中的邮箱
import re
text = "楼主太牛逼了一giao我里giao,在线想要 598779784@qq.com,搞起来呀"
phone_list = re.findall("\d{4,9}@qq.com", text)
print(phone_list) # ['598779784@qq.com']
正则语法
常用元字符
.匹配除换行符以外的任意字符
^匹配字符串的开始(多行情况下匹配每一行的开头)
$匹配字符串的结束(多行情况下匹配每一行的开头)
\b匹配单词的开始或结束
\d匹配一个数字 相当于[0-9]
\s匹配一个空格(也包括Tab等空白符)相当于[\t\n\r\f\v]
\w匹配一个字母或数字 [a-zA-Z0-9]
\A 仅匹配字符串的开头,类似 ^, 但不处理多行
\B 匹配不是单词开头或结束的位置
\D 匹配任意非数字的字符 相当于[^0-9]
\S 匹配任意不是空白符的字符 [^\t\n\r\f\v]
\W 匹配任意不是字母,数字,下划线,汉字的字符 [^a-zA-Z0-9]
[^x] 匹配除了x以外的任意字符
[^abcdef] 匹配除了abcdef这几个字母以外的任意字符
\Z 仅匹配字符串的结尾,类似 $, 但不处理多行
常用限定符
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{m,n} 重复m到n次
贪婪与懒惰
(正则匹配默认是贪婪匹配,加个?就可以非贪婪匹配)
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
字符转义
\ 来取消这些字符的特殊意义
\\ \
\. .
\* *
分组
(?P<name>...) 通过group方法访问
符号:.、^、$、*、+、?、{}、[]、\、|、()
文件名匹配:?代表一个字符,*代表多个字符
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’)]
- match,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None
```python
import re
text = "大小逗2B最逗3B欢乐"
data = re.match("逗\dB", text)
print(data) # None
import re
text = "逗2B最逗3B欢乐"
data = re.match("逗\dB", text)
if data:
content = data.group() # "逗2B"
print(content)
- search,浏览整个字符串去匹配第一个,未匹配成功返回None ```python import re
text = “大小逗2B最逗3B欢乐” data = re.search(“逗\dB”, text) if data: print(data.group()) # “逗2B”
- sub,替换匹配成功的位置
```python
import re
text = "逗2B最逗3B欢乐"
data = re.sub("\dB", "沙雕", text)
print(data) # 逗沙雕最逗沙雕欢乐
import re
text = "逗2B最逗3B欢乐"
data = re.sub("\dB", "沙雕", text, 1)
print(data) # 逗沙雕最逗3B欢乐
- split,根据匹配成功的位置分割 ```python import re
text = “逗2B最逗3B欢乐” data = re.split(“\dB”, text) print(data) # [‘逗’, ‘最逗’, ‘欢乐’]
```python
import re
text = "逗2B最逗3B欢乐"
data = re.split("\dB", text, 1)
print(data) # ['逗', '最逗3B欢乐']
- finditer
python正则模块re中findall和finditer两者相似,但却有很大区别。
两者都可以获取所有的匹配结果,这和findall方法有着很大的区别,同时不同的是一个返回list,一个返回一个MatchObject类型的iterator
import re
text = "逗2B最逗3B欢乐"
data = re.finditer("\dB", text)
for item in data:
print(item.group())
# 有名分组
import re
text = "逗2B最逗3B欢乐"
data = re.finditer("(?P<xx>\dB)", text) # 命名分组
for item in data:
print(item.groupdict())
# {'xx': '2B'}
# {'xx': '3B'}
import re
text = "dsf130429191912015219k13042919591219521Xkk"
data_list = re.finditer("\d{6}(?P<year>\d{4})(?P<month>\d{2})(?P<day>\d{2})\d{3}[\d|X]", text)
for item in data_list:
info_dict = item.groupdict()
print(info_dict)
# {'year': '1919', 'month': '12', 'day': '01'}
# {'year': '1959', 'month': '12', 'day': '19'}
【标志位】
使用较少,
第三个参数,默认flags=0
re.DEBUG re.M re.U re.error re.search re.sys
re.DOTALL re.MULTILINE re.UNICODE re.escape re.split re.template
re.I re.S re.VERBOSE re.findall re.sre_compile
re.IGNORECASE re.Scanner re.X re.finditer re.sre_parse
re.L re.T re.compile re.match re.sub
re.LOCALE re.TEMPLATE re.copy_reg re.purge re.subn
re.M //识别\n,将一个字符串按\n分成多个
In [1]: import re
In [2]: data = 'foo1\nfoo2\n'
In [3]: re.findall(r'foo.$',data)
Out[3]: ['foo2']
In [4]: re.findall(r'foo.$',data,re.M)
Out[4]: ['foo1', 'foo2']
compile语法
可以把正则语法单独拿出来
import re
text = "逗2B最逗3B欢乐"
re_text = re.compile('\dB', re.M)
data = re.sub(re_text, "沙雕", text)
print(data) # 逗沙雕最逗沙雕欢乐
实战一
1. 字符相关
mufeng
匹配文本中的mufeng
```python import re
text = “你好mufeng,阿斯顿发wupeiqasd 阿士大夫能接受的mufengff” data_list = re.findall(“mufeng”, text) print(data_list) # [‘mufeng’, ‘mufeng’] 可用于计算字符串中某个字符出现的次数
- `[abc]` 匹配a或b或c 字符。
```python
import re
text = "你好mufeng,阿斯顿发wupeiqasd 阿士大夫能接受的bbupqaceiqiff"
data_list = re.findall("[abc]", text)
print(data_list) # ['a', 'b', 'b', 'a', 'c']
import re
text = "你好mufeng,阿斯顿发wupeiqasd 阿士大夫能接受的bbupqaceiqiff"
data_list = re.findall("q[abc]", text)
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’]
- `[a-z]` 匹配a~z的任意字符( [0-9]也可以 )。
```python
import re
text = "mufengrootrootadmin"
data_list = re.findall("t[a-z]", text)
print(data_list) # ['tr', 'ta']
.
代指除换行符以外的任意字符。 ```python import re
text = “mufengrootrootadmin” data_list = re.findall(“r.o”, text) print(data_list) # [‘rao’, ‘roo’]
```python
import re
text = "mufengrootrootadmin"
data_list = re.findall("r.+o", text) # 贪婪匹配
print(data_list) # ['raotroo']
\w
代指字母或数字或下划线(汉字)。 ```python import re
text = “北京沐风ecithy 江苏沐风deepwind” data_list = re.findall(“沐风\w+”, text) print(data_list) # [‘沐风ecithy’, ‘沐风deepwind’]
- `\d` 代指数字
```python
import re
text = "root-ad32min-add3-admd1in"
data_list = re.findall("d\d", text)
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’]
<a name="GALJt"></a>
### 2. 数量相关
- `*` 重复0次或更多次
```python
import re
text = "他是大B个,确实是个大2B。"
data_list = re.findall("大2*B", text)
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’]
- `?` 重复0次或1次
```python
import re
text = "他是大B个,确实是个大2B,大3B,大66666B。"
data_list = re.findall("大\d?B", text)
print(data_list) # ['大B', '大2B', '大3B']
{n}
重复n次
import re
text = "楼主太牛逼了,在线想要 598779784@qq.com和xxxxx@live.com谢谢楼主,手机号也可18879404697,搞起来呀"
data_list = re.findall("188794\d{5}", text)
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’]
- `{n,m}` 重复n到m次
```python
import re
text = "楼主太牛逼了,在线想要 598779784@qq.com和xxxxx@live.com谢谢楼主,手机号也可18879404697,搞起来呀"
data_list = re.findall("188794\d{3,9}", text)
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’]
```python
import re
text = "楼主太牛逼了,在线想要 598779784@qq.com和xxxxx@live.com谢谢楼主,手机号也可18879404697,搞起来呀"
data_list = re.findall("188(79)(\d{5,})", text)
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’]
<a name="KNXx1"></a>
### 4. 起始和结束
上述示例中都是去一段文本中提取数据,只要文本中存在即可。<br />但,如果要求用户输入的内容必须是指定的内容开头和结尾,比就需要用到如下两个字符。<br />这种一般用于对用户输入数据格式的校验比较多,例如:
```python
import re
text = "598779784@qq.com"
email_list = re.findall("^\w+@\w+.\w+$", text, re.ASCII)
print(email_list) # []
实战二
import re
text = "我的企鹅号是598779784, 小号是649848996964"
data_list = re.findall("[1-9]\d{4,}", text)
print(data_list) # ['598779784', '649848996964']
手机号
import re
text = "我的手机号是18879404697, 小号是16679404698"
data_list = re.findall("\d{11}", text)
print(data_list) # ['18879404697', '16679404698']
邮箱地址
import re
# 汉字范围: [\u4E00-\u9FA5]
text = "我的手机号是18879404697@126.com, 小号是598779784@qa.com"
data_list = re.findall("[\u4E00-\u9FA5]+(\w+@\w+\.\w+)",text)
print(data_list) # ['18879404697@126.com', '598779784@qa.com']