05.数据解析之正则表达式

1、正则表达式

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。——百度百科

下面是正则表达式常见的使用场景:

  1. 检查字符串的合法性
  • 验证用户名 (a-z,0-9,不能全是数字,不能全是字母)
  • 验证邮箱格式 (xxx@qq.com)
  • 验证电话号码 (11位数字)
  • 验证身份证 (18位 )
  • 验证QQ号码格式(5-12纯数字,第一位不能为0);
  1. 提取字符串中信息
  • 提取一条短信中数字;
  • 提取文件名的后缀;
  • 采集器(网络爬虫)
  1. 替换字符串
  • 替换字符串中的非法字符;
  • 对电话号码进行屏蔽;(18520102)
  • 替换占位符 “hello {{name}} ” hello 王老二 (模板框架)
  1. 分割字符串
  • 将一个字符串按照指定的规则进行分割;

在爬虫中,使用正则表达式提取我们想要的数据。去掉多余的数据。

场景:找所有邮件地址

百度贴吧邮箱信息:http://tieba.baidu.com/p/5781191467

text = """
回复(2)4楼2018-07-04 11:48哥哥口袋有糖
初识物联1
346504108@qq.com收起回复5楼2018-07-04 14:10Super劫Zed: 540775360@qq.com
2018-8-8 16:00回复
我也说一句RAVV2017
物联硕士4
以上的邮箱,已发,还需要的请回复邮箱。两套物联网学习资料。回复(4)7楼2018-07-04 16:06儒雅的刘飞3
初识物联1
397872410@qq.com,谢谢楼主收起回复8楼2018-07-04 16:20RAVV2017: 已发送,麻烦请查收,谢谢
2018-7-4 16:23回复
我也说一句该来的总会来
物联博士5
1459543548@qq.com
谢谢谢谢回复9楼2018-07-04 17:18来自Android客户端
BLACKPINK_罗捷
深入物联2
1228074244@qq.com
"""

1、1 元字符

使用元字符匹配单个字符

字符功能
.匹配任意1个字符(除了\n)
[ ]匹配[ ]中列举的字符
\d匹配数字,即0-9
\D匹配非数字,即不是数字
\s匹配空白,即 空格,tab键,换行
\S匹配非空白(数字、英文字符、特殊符号)
\w匹配单词字符,即a-z、A-Z、0-9、_
\W匹配非单词字符
*匹配前一个字符出现0次或者无限次,即可有可无
+匹配前一个字符出现1次或者无限次,即至少有1次
\d匹配数字
#coding=utf-8import reres = re.findall("\d"'346504108@qq.com')
print(res)

运行结果:

['3''4''6''5''0''4''1''0''8']
+ * 匹配多个字符
import reres = re.findall("\d+"'346504108@qq.com')
print(res)

运行结果:

['346504108']
\d与[](字符集)

可能会出现的一些情况

[123456zxcv] 字符集只能匹配一个出现在集合里面的值

\d代表0到9的所有数字,[0123456789] 与\d等效

import reres = re.findall("\d+"'346504108@qq.com')
print(res)res1 = re.findall("[0123456789]+"'346504108@qq.com')
print(res1)

运行结果:

['346504108']
['346504108']

思考:邮箱可能出现为字符串,该如何处理?

例如:yanglong985@163.com

提示: [a-z]

使用点匹配任意字符

案例:匹配中国电信手机号码

  • 中国电信号段
    133. 153. 180. 189
  • 号码总长度为11位

实现方式:

  1. 编写电信号码的正则
  2. 进行匹配
  3. 打印结果
import restr_phone = """13357024777
电信 浙江省 衢州 尾数AAA 号码吉凶
18948121234 
电信 广东省 茂名 尾数ABCD 号码吉凶
13873179698 
移动 湖南省 长沙 个性靓号 号码吉凶
15802648889 
移动 湖南省 长沙 尾数AAABAAAB号码吉凶
"""# 第一位都是以1开头 第二位可以为34578 第三位没有6与9 后面都是数字
res = re.findall('1[358][039]\d+', str_phone)
print(res)
使用.*匹配任意多个字符

思考:匹配 HelloDemo 之间的内容

import recontent = 'Hello 1234567 World_This is a Rexgex Demo'
result = re.findall('Hel.* Rexgex Demo', content)
print(result)

1、2 数量词

使用数量词匹配多个字符

字符功能
{m}匹配前一个字符出现0 到 m 次
{m,n}匹配前一个字符出现从m到n次

需求:匹配出,8到20位的密码,可以是大小写英文字母、数字、下划线

#coding=utf-8
import reres = re.findall("[a-zA-Z0-9]{8}""ash2e223 3424kjkljkljf 34523nmkdsjf")
print(res)ret = re.findall("[a-zA-Z0-9_]{8,20}""ash2e223 3424kjkljkljf 34523nmkdsadsjf")
print(ret)

案例:QQ 号码匹配

  • QQ 号规则
    1. 第一位数字不能为0
    2. 可能是 5-12 位
qq_str = """
346504108@qq.com
Super劫Zed: 540775360@qq.com
397872410@qq.com,谢谢楼主
1459543548@qq.com
"""result = re.findall("[1-9][0-9]{4,11}",qq_str)
print(result)

运行结果:

['346504108''540775360''397872410''1459543548']

1、3 精确匹配与泛匹配

泛匹配

泛匹配是匹配所有的东西

import recontent = 'Hello 1234567 World_This is a Rexgex Demo'result = re.find('Hello.*Demo', content)
print(result)
精确匹配

精确匹配是匹配括号里面的东西

import recontent = 'Hello 1234567 World_This is a Rexgex Demo'
result = re.findall('Hello (\d+).*Demo', content)
print(result)

1、4 贪婪匹配与非贪婪匹配

Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;

非贪婪则相反,总是尝试匹配尽可能少的字符。

在"*“,”?“,”+“,”{m,n}"后面加上?,使贪婪变成非贪婪。

import recontent = 'Hello 1234567 World_This is a Rexgex Demo'
result = re.findall('Hel.*(\d+)', content)
print(result)

​ 正则表达式模式中使用到通配字,那它在从左到右的顺序求值时,会尽量“抓取”满足匹配最长字符串,在我们上面的例子里面,“.+”会从字符串的启始处抓取满足模式的最长字符,其中包括我们想得到的第一个整型字段的中的大部分,“\d+”只需一位字符就可以匹配,所以它匹配了数字“4”,而“.+”则匹配了从字符串起始到这个第一位数字4之前的所有字符。

解决方式:非贪婪操作符“?”,这个操作符可以用在"*“,”+“,”?"的后面,要求正则匹配的越少越好。

2、re模块

​ 一直以来我们都是使用 re.search() 函数,其实在正则表达式模块中还有一些函数可以很方便的对字符串进行操作。re模块的使用可以分为两种:第一种是对象式的方式,第二种是函数式的方式

2、1re.match

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

match(pattern, string[, flag])

其中,pattern是正则表达式规则字符串,string 是待匹配的字符串,flag 是可选参数。

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

# 导入模块
import re
# 正则
pattern = 'Python'
# 字符串
string = 'PythonahsdgjasghPythonasdjajsk'
# 匹配
result = re.match(pattern, string)
# 结果
print(result)

2、2 re.search

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

search(pattern, string[, flag])

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

ret = re.search('\d+', "python = 9999, c = 7890, c++ = 12345")
ret.group()

2、3 re.findall

上面的 matchsearch 方法都是一次匹配,只要找到了一个匹配的结果就返回。然而,在大多数时候,我们需要搜索整个字符串,获得所有匹配的结果。findall() 的使用形式如下:

findall(pattern, string[, flag])

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

ret = re.findall(r"\d+", "python = 9999, c = 7890, c++ = 12345")
print(ret)

2、4 re.split

split()按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

split(pattern, string[, maxsplit, flags])

其中,maxsplit 用于指定最大分割次数,不指定将全部分割。

'''
split():分割字符串 去掉了匹配到的字符串 结果是列表形式maxsplit: 默认是0 表示全部切割1 代表切割一次2 代表切割两次
'''
import re
pattern = '\d+'
string = 'Pythonasdkjasd464654adhuiaghsdk564654akjsdhkashdkja'
result = re.split(pattern, string, 2)
print(result)

2、5 re.sub

sub()用于替换,使用形式如下:

sub(pattern, repl, string[, count, flags])

第一个参数为对应的正则表达式,第二个参数为要替换成的字符串,第三个参数为源字符串,第四个参数为可选项,代表最多替换的次数,如果忽略不写,则会将符合模式的结果全部替换。

'''
re.sub(pattern, repl, string, count=0, flags=0): 替换匹配到的字符串 pattern: 正则repl: 要替换的字符串string: 待替换的字符串count: 替换的次数0 全部替换 1 --> 替换一次2 --> 替换两次'''
import re
pattern = 'Java'
repl = 'Python'
string = 'PythonasdkjasdJavaadhuiaghsdkJavaakjsdhkashdkja'
result = re.sub(pattern, repl, string)
print(result)
  • 参数flags

方法1:

ret = re.sub(r"\d+", '998', "python = 997")
print(ret)

运行结果:

python = 998

方法2:

def add(temp):strNum = temp.group()num = int(strNum) + 1return str(num)ret = re.sub(r"\d+", add, "python = 997 python = 996")
print(ret)

运行结果:

python = 998

2、6 re.compile

使用 compile() 函数将正则表达式的字符串形式编译为一个 Pattern 对象。通过该对象提供的一系列方法对文本进行匹配查找,获得匹配结果(Match对象)。编译可以实现更高效的匹配查找等。

  • compile()函数

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

import re
# 将正则表达式编译成 Pattern 对象
pattern = re.compile('\d+', re.S)

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

将正则表达式字符串编译成正则对象,以便于复用该模式

results1 = re.findall(pattern, '540775360@qq.com')
results2 = re.findall(pattern, "python = 9999, c = 7890, c++ = 12345")
results3 = re.findall(pattern, "python = 997")
print(results1, results2, results3)
示例1:

需求:匹配出0-100之间的数字

#coding=utf-8import reret = re.match("[1-9]?\d""8")
print(ret.group())  # 8ret = re.match("[1-9]?\d""78")
print(ret.group())  # 78# 不正确的情况
ret = re.match("[1-9]?\d""08")
print(ret.group())  # 0# 修正之后的
ret = re.match("[1-9]?\d$""08")
if ret:print(ret.group())
else:print("不在0-100之间")# 添加|
ret = re.match("[1-9]?\d$|100""8")
print(ret.group())  # 8ret = re.match("[1-9]?\d$|100""78")
print(ret.group())  # 78ret = re.match("[1-9]?\d$|100""08")
# print(ret.group())  # 不是0-100之间ret = re.match("[1-9]?\d$|100""100")
print(ret.group())  # 100
示例2:

需求:匹配出163、126、qq邮箱

#coding=utf-8import reret = re.match("\w{4,20}@163\.com""test@163.com")
print(ret.group())  # test@163.comret = re.match("\w{4,20}@(163|126|qq)\.com""test@126.com")
print(ret.group())  # test@126.comret = re.match("\w{4,20}@(163|126|qq)\.com""test@qq.com")
print(ret.group())  # test@qq.comret = re.match("\w{4,20}@(163|126|qq)\.com""test@gmail.com")
if ret:print(ret.group())
else:print("不是163、126、qq邮箱")  # 不是163、126、qq邮箱

不是以4、7结尾的手机号码(11位)

import retels = ["13100001234""18912344321""10086""18800007777"]for tel in tels:ret = re.match("1\d{9}[0-35-68-9]", tel)if ret:print(ret.group())else:print("%s 不是想要的手机号" % tel)

2、7 原始字符串

>>> mm = "c:\\a\\b\\c"
>>> mm
'c:\\a\\b\\c'
>>> print(mm)
c:\a\b\c
>>> re.match("c:\\\\",mm).group()
'c:\\'
>>> ret = re.match("c:\\\\",mm).group()
>>> print(ret)
c:\
>>> ret = re.match("c:\\\\a",mm).group()
>>> print(ret)
c:\a
>>> ret = re.match(r"c:\\a",mm).group()
>>> print(ret)
c:\a
>>> ret = re.match(r"c:\a",mm).group()
Traceback (most recent call last):File "<stdin>", line 1in <module>
AttributeError: 'NoneType' object has no attribute 'group'
>>>

Python中字符串前面加上 r 表示原生字符串

与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"“,那么使用编程语言表示的正则表达式里将需要4个反斜杠”\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。

Python里的原生字符串很好地解决了这个问题,有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。

>>> ret = re.match(r"c:\\a",mm).group()
>>> print(ret)
c:\a

2、8 匹配开头结尾

字符功能
^匹配字符串开头
$匹配字符串结尾
末尾匹配

需求:匹配163.com的邮箱地址

#coding=utf-8import reemail_list = ["xiaoWang@163.com""xiaoWang@163.comheihei"".com.xiaowang@qq.com"]for email in email_list:ret = re.match("[\w]{4,20}@163\.com", email)if ret:print("%s 是符合规定的邮件地址,匹配后的结果是:%s" % (email, ret.group()))else:print("%s 不符合要求" % email)

运行结果:

xiaoWang@163.com 是符合规定的邮件地址,匹配后的结果是:xiaoWang@163.com
xiaoWang@163.comheihei 是符合规定的邮件地址,匹配后的结果是:xiaoWang@163.com
.com.xiaowang@qq.com 不符合要求

完善后

email_list = ["xiaoWang@163.com""xiaoWang@163.comheihei"".com.xiaowang@qq.com"]for email in email_list:ret = re.match("[\w]{4,20}@163\.com$", email)if ret:print("%s 是符合规定的邮件地址,匹配后的结果是:%s" % (email, ret.group()))else:print("%s 不符合要求" % email)

运行结果:

xiaoWang@163.com 是符合规定的邮件地址,匹配后的结果是:xiaoWang@163.com
xiaoWang@163.comheihei 不符合要求
.com.xiaowang@qq.com 不符合要求

万能正则

(.\*?) 匹配除了换行以外的任意字符串。无论长短,最多匹配一次,非贪婪匹配。

这个正则表达式可以解决你想要提取的大部分数据,在写正则表达式的时候可以首先尝试这个组合,也许能达到事半功倍的效果。并且常常结合re.findall()函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/95908.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

下载 VMware Workstation Pro

https://www.vmware.com/cn/products/workstation-pro/workstation-pro-evaluation.html

asp.net班级管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net班级管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发 asp.net班级管理系统 二、功能介绍 1…

国庆作业 day 2

select实现服务器并发 #include<myhead.h> #define ERR_MSG(msg) do{\fprintf(stderr, "__%d__:", __LINE__); \perror(msg);\ }while(0)#define PORT 8888 //端口号&#xff0c;范围1024~49151 #define IP "192.168.0.103" //本…

c++运算符重载实现

#include <iostream> #include <cstring> using namespace std; class myString { private:char *str;int size; public://无参构造myString():size(10){str new char[size]; //构造出一个长度为10的字符串strcpy(str,""); //赋值为空串}//有…

基于transformer的心脑血管心脏病疾病预测

视频讲解:基于transformer的心脑血管疾病预测 完整数据代码分享_哔哩哔哩_bilibili 数据展示: 完整代码: # pip install openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple/ # pip install optuna -i https://pypi.tuna.tsinghua.edu.cn/simple/ import numpy as np …

硬件知识:U盘相关知识介绍,值得收藏

目录 什么是U盘&#xff1f; U盘根据结构有哪几种&#xff1f; 根据U盘的存储介质、外形、功能分类有哪几种&#xff1f; 什么是U盘&#xff1f; U盘&#xff0c;全称为USB闪存盘&#xff0c;是一种以闪存芯片作为数据存储介质的移动存储设备。U盘的历史可以追溯到1998年&am…

优化方法的应用(optimtool.example)

import optimtool as oo from optimtool.base import np, sp, pltpip install optimtool>2.4.2优化方法的应用&#xff08;optimtool.example&#xff09; import optimtool.example as oeLasso问题&#xff08;Lasso&#xff09; oe.Lasso.[函数名]([矩阵A], [矩阵b], [因…

【MQTT】mosquitto库中SSL/TLS相关API接口

文章目录 1.相关API1.1 mosquitto_tls_set1.2 mosquitto_tls_insecure_set1.3 mosquitto_tls_opts_set1.4 mosquitto_tls_insecure_set1.5 mosquitto_tls_set_context1.6 mosquitto_tls_psk_set 2.示例代码 Mosquitto 是一个流行的 MQTT 消息代理&#xff08;broker&#xff09…

Spring基础以及核心概念(IoC和DIQ)

1.Spring是什么 Spring是包含了众多工具方法的IoC容器 2.loC&#xff08;Inversion of Control &#xff09;是什么 IoC:控制反转,Spring是一个控制反转容器(控制反转对象的生命周期) Spring是一个loC容器&#xff0c;我们之前学过的List/Map就是数据存储的容器&#xff0c;to…

Java项目防止SQL注入的四种方案

&#x1f514;1. 什么是SQL注入&#xff1f; SQL注入(SQL Injection)是一种代码注入技术,是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。简单来说,SQL注入攻击者通过把SQL命令插入到Web表单提交或输入域名或页面请…

Naive UI 文档地址

最近几天官网访问不了&#xff0c;自己用github pages 部署了个 官网 github pages

搭建在线python运行环境

常遇到需要一个小工具&#xff0c;比如生成作息时间表&#xff0c;今天就搭建一个可在线使用的python运行环境 当然也可以交给ChatGPT完成 1、安装canda wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2019.03-Linux-x86_64.shyum install -y bzi…

c#设计模式-结构型模式 之 装饰者模式

&#x1f680;介绍 在装饰者模式中&#xff0c;装饰者类通常对原始类的功能进行增强或减弱。这种模式是在不必改变原始类的情况下&#xff0c;动态地扩展一个对象的功能。这种类型的设计模式属于结构型模式&#xff0c;因为这种模式涉及到两个类型之间的关系&#xff0c;这两个…

637. 二叉树的层平均值

637. 二叉树的层平均值 原题 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode…

时序预测 | MATLAB实现EMD-iCHOA+GRU基于经验模态分解-改进黑猩猩算法优化门控循环单元的时间序列预测

时序预测 | MATLAB实现EMD-iCHOAGRU基于经验模态分解-改进黑猩猩算法优化门控循环单元的时间序列预测 目录 时序预测 | MATLAB实现EMD-iCHOAGRU基于经验模态分解-改进黑猩猩算法优化门控循环单元的时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 EMD-iCHOAGR…

【C语言】利用数组处理批量数据(字符数组)

前言:前面已经介绍了&#xff0c;字符数据是以字符的ASCII代码存储在存储单元中的&#xff0c;一般占一个字节。由于ASCII代码也属于整数形式&#xff0c;因此在C99标准中&#xff0c;把字符类型归纳为整型类型中的一种。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x…

(32)测距仪(声纳、激光雷达、深度摄影机)

文章目录 前言 32.1 单向测距仪 32.2 全向性近距离测距仪 32.3 基于视觉的传感器 前言 旋翼飞机/固定翼/无人车支持多种不同的测距仪&#xff0c;包括激光雷达&#xff08;使用激光或红外线光束进行距离测量&#xff09;、360 度激光雷达&#xff08;可探测多个方向的障碍…

Java中阻塞队列原理、特点、适用场景

文章目录 阻塞队列对比、总览阻塞队列本质思想主要队列讲解ArrayBlockingQueueLinkedBlockingQueueSynchronousQueueLinkedTransferQueuePriorityBlockingQueueDelayQueueLinkedBlockingDeque 阻塞队列对比、总览 阻塞队列本质思想 阻塞队列都是线程安全的队列. 其最主要的功能…

打印选课学生名单(应用map,set)

假设全校有最多40000名学生和最多2500门课程。现给出每个学生的选课清单&#xff0c;要求输出每门课的选课学生名单。 输入格式: 输入的第一行是两个正整数&#xff1a;N&#xff08;≤40000&#xff09;&#xff0c;为全校学生总数&#xff1b;K&#xff08;≤2500&#xff0…

Oracle修改表空间文件位置

登录oracle用户su - oracle 关闭监听lsnrctl stop 关闭数据库 sqlplus / as sysdba shutdown immediate 移动表空间文件导入新的位置 cd /u01/app/oracle/oradata/CDB1/ mv sfz.dbf to /opt/oracledata/sfz.dbf chown -R oracle:oinstall /opt/oracledata/挂起数据库 sqlp…