【Python爬虫实战】正则:多字符匹配、开头与结尾定位、分组技术详解
🌈个人主页:https://blog.csdn.net/2401_86688088?type=blog
🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html
目录
前言
一、匹配多个字符
(一)匹配任意多个字符
(二)匹配一个或多个字符
(三)匹配特定数量的字符
(四)匹配字符范围
(五)匹配非数字、非字母等
(六)使用 re.DOTALL 匹配多行
(七)匹配指定开头或结尾的多个字符
(八)匹配字母、数字、空白符
(九)匹配多个字符总结
二、匹配开头和结尾
(一)匹配字符串的开头:^
(二)匹配字符串的结尾:$
(三)同时匹配开头和结尾
(四)匹配多行模式
(五)示例:验证电子邮件
(六)匹配开头和结尾总结
三、匹配分组
(一)基本分组
(二)命名分组
(三)非捕获分组
(四)使用 groups() 提取所有分组
(五)反向引用分组
(六)分组嵌套
(七)忽略大小写和多行分组匹配
(八)匹配分组总结
四、总结
前言
正则表达式是一种灵活且强大的工具,用于匹配和操作文本。它广泛应用于编程、文本处理、数据清理和验证等领域。在 Python 中,通过内置的 re
模块,开发者可以轻松使用正则表达式来解决复杂的文本匹配问题。本篇文章详细介绍了正则表达式中的多字符匹配、开头和结尾匹配、分组匹配等重要概念及其应用。通过这些示例与技巧,读者将能够掌握如何在 Python 中运用正则表达式处理多种场景下的文本操作需求。
一、匹配多个字符
在正则表达式中,匹配多个字符的方式取决于你要匹配的字符类型和数量。正则表达式通过量词和字符集的组合,能够灵活地匹配任意长度的字符串。以下是一些常见的正则匹配多个字符的方式:
(一)匹配任意多个字符
使用 .*
匹配任意多个字符(包括0个),其中 .
表示任意单个字符,*
表示前面的字符出现0次或多次。
示例:
import re
text = "hello world"
result = re.findall(r'.*', text)
print(result) # 输出: ['hello world', '']
(二)匹配一个或多个字符
使用 +
匹配前面的字符一次或多次,保证至少匹配一个字符。
示例:
import re
text = "abc123"
result = re.findall(r'\d+', text)
print(result) # 输出: ['123']
(三)匹配特定数量的字符
-
使用
{n}
来精确匹配前面的字符n
次。 -
使用
{n,m}
来匹配前面的字符至少n
次,至多m
次。
示例:
import re
text = "12345"
# 匹配恰好5个数字
result = re.findall(r'\d{5}', text)
print(result) # 输出: ['12345']
(四)匹配字符范围
使用字符集 []
匹配多个特定字符,或者使用字符范围(如 [a-z]
)来匹配多个连续字符。
示例:
import re
text = "abcdef123"
result = re.findall(r'[a-f]+', text) # 匹配a-f范围内的多个字符
print(result) # 输出: ['abcdef']
(五)匹配非数字、非字母等
使用反向匹配 [^]
来匹配多个不属于某类的字符。例如,[^0-9]+
匹配非数字的字符序列。
示例:
import re
text = "abc123def"
# 匹配非数字的字符序列
result = re.findall(r'[^0-9]+', text)
print(result) # 输出: ['abc', 'def']
(六)使用 re.DOTALL
匹配多行
使用 re.DOTALL
标志符,使 .
能够匹配包括换行符在内的所有字符,通常用于匹配跨多行的文本。
示例:
import re
text = "line1\nline2"
# 不使用 DOTALL,无法匹配换行符
result = re.findall(r'.+', text)
print(result) # 输出: ['line1', 'line2']# 使用 DOTALL,可以匹配换行符
result = re.findall(r'.+', text, re.DOTALL)
print(result) # 输出: ['line1\nline2']
(七)匹配指定开头或结尾的多个字符
使用 ^
表示匹配字符串的开头,$
表示匹配字符串的结尾。例如 ^abc
匹配以 abc
开头的字符串,abc$
匹配以 abc
结尾的字符串。
示例:
import re
text = "abc123abc"
# 匹配以 abc 开头的字符串
result = re.findall(r'^abc', text)
print(result) # 输出: ['abc']# 匹配以 abc 结尾的字符串
result = re.findall(r'abc$', text)
print(result) # 输出: ['abc']
(八)匹配字母、数字、空白符
-
使用
\w+
匹配多个字母、数字或下划线字符。 -
使用
\d+
匹配多个数字。 -
使用
\s+
匹配多个空白字符(如空格、制表符、换行符)。
示例:
import re
text = "abc 123"
# 匹配多个字母或数字
result = re.findall(r'\w+', text)
print(result) # 输出: ['abc', '123']# 匹配多个空格
result = re.findall(r'\s+', text)
print(result) # 输出: [' ']
(九)匹配多个字符总结
正则表达式可以通过使用量词、字符集和特殊符号来匹配多个字符。无论是匹配任意字符、特定字符、字符集,还是根据字符出现次数来匹配,正则表达式都可以提供灵活和强大的解决方案。熟练掌握这些技巧后,你可以有效处理多种文本处理需求。
二、匹配开头和结尾
在正则表达式中,使用 ^
和 $
分别可以匹配字符串的开头和结尾。它们的具体用法如下:
(一)匹配字符串的开头:^
^
用于匹配字符串的开头。只有当字符串以指定的模式开头时,才会匹配成功。
示例: 假设我们想匹配以 "hello"
开头的字符串:
import re
text = "hello world"
result = re.findall(r'^hello', text)
print(result) # 输出: ['hello']
如果字符串不是以 "hello"
开头,则匹配会失败:
text = "world hello"
result = re.findall(r'^hello', text)
print(result) # 输出: []
(二)匹配字符串的结尾:$
$
用于匹配字符串的结尾。只有当字符串以指定的模式结尾时,才会匹配成功。
示例: 假设我们想匹配以 "world"
结尾的字符串:
import re
text = "hello world"
result = re.findall(r'world$', text)
print(result) # 输出: ['world']
如果字符串不是以 "world"
结尾,则匹配会失败:
text = "world hello"
result = re.findall(r'world$', text)
print(result) # 输出: []
(三)同时匹配开头和结尾
可以结合 ^
和 $
同时使用,来匹配整个字符串的模式。例如,匹配完整的字符串 "hello world"
:
import re
text = "hello world"
result = re.findall(r'^hello world$', text)
print(result) # 输出: ['hello world']
示例:
import re
text = "hello world"
result = re.findall(r'^hello world$', text)
print(result) # 输出: ['hello world']
这个模式要求整个字符串必须是 "hello world"
,否则匹配不会成功:
text = "hello world!"
result = re.findall(r'^hello world$', text)
print(result) # 输出: []
(四)匹配多行模式
默认情况下,^
和 $
只会匹配整个字符串的开头和结尾。如果要在多行字符串中分别匹配每一行的开头和结尾,可以使用 re.MULTILINE
标志。
示例:
import re
text = """hello world
goodbye world"""
# 匹配每行的开头为 'hello' 或 'goodbye'
result = re.findall(r'^(hello|goodbye)', text, re.MULTILINE)
print(result) # 输出: ['hello', 'goodbye']
在这种情况下,^
和 $
会作用于每一行的起始和结束位置,而不仅仅是整个字符串的起始和结束。
(五)示例:验证电子邮件
假设我们需要验证电子邮件地址的格式,要求它以字母或数字开头,包含 @
,并以域名结尾。可以结合 ^
和 $
来确保整个字符串符合电子邮件格式:
import re
email = "user@example.com"
pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
result = re.match(pattern, email)
if result:print("有效的电子邮件地址")
else:print("无效的电子邮件地址")
(六)匹配开头和结尾总结
匹配开头和结尾总结起来有以下几点:
-
^
用于匹配字符串的开头。 -
$
用于匹配字符串的结尾。 -
re.MULTILINE
标志可以使^
和$
作用于每一行的开头和结尾,而不仅限于整个字符串。 -
结合
^
和$
可以确保整个字符串完全匹配特定的模式。
三、匹配分组
正则表达式中的分组功能可以通过使用圆括号 ()
来实现,分组的作用是将表达式的某一部分进行分组匹配,并可以通过分组提取具体的匹配结果。分组是正则表达式非常强大的功能,允许我们对匹配的结果进行更灵活的操作。
(一)基本分组
使用圆括号 ()
来将正则表达式中的某个部分进行分组。分组的内容会被单独提取出来,分组后可以通过 Match
对象的 .group()
或 .groups()
方法来获取匹配的分组内容。
示例:匹配并提取姓名和年龄
import re
text = "姓名: 张三, 年龄: 25"
# 使用分组来分别匹配姓名和年龄
pattern = r"姓名:\s(\w+),\s年龄:\s(\d+)"
result = re.search(pattern, text)if result:print(result.group(1)) # 输出: 张三print(result.group(2)) # 输出: 25
在上面的例子中,正则表达式中的两个括号分别对名字和年龄进行了分组,因此可以通过 group(1)
和 group(2)
来获取第一个和第二个匹配的分组。
(二)命名分组
命名分组允许你为分组指定一个名字,这样你可以通过分组名称来访问匹配结果,而不是使用数字索引。命名分组的语法是 (?P<name>...)
,其中 name
是分组的名字。
示例:使用命名分组提取姓名和年龄
import re
text = "姓名: 李四, 年龄: 30"
# 使用命名分组为姓名和年龄命名
pattern = r"姓名:\s(?P<name>\w+),\s年龄:\s(?P<age>\d+)"
result = re.search(pattern, text)if result:print(result.group("name")) # 输出: 李四print(result.group("age")) # 输出: 30
在这种方式下,你可以通过分组的名称 name
和 age
来提取匹配的内容,代码更加清晰。
(三)非捕获分组
有时我们只想对表达式进行分组,而不希望捕获这个分组的匹配结果。可以使用 (?:...)
来创建一个非捕获分组。这样该分组参与匹配,但不会出现在匹配的结果中。
示例:使用非捕获分组
import re
text = "apple, banana, cherry"
# 使用非捕获分组来匹配不同的水果
pattern = r"(?:apple|banana|cherry)"
result = re.findall(pattern, text)
print(result) # 输出: ['apple', 'banana', 'cherry']
在这个例子中,(?:...)
只是用来匹配,但不会被作为分组结果提取。
(四)使用 groups()
提取所有分组
使用 groups()
可以一次性提取所有分组的匹配内容,返回的是一个包含所有分组内容的元组。
示例:提取所有分组内容
import re
text = "姓名: 王五, 年龄: 40"
pattern = r"姓名:\s(\w+),\s年龄:\s(\d+)"
result = re.search(pattern, text)if result:print(result.groups()) # 输出: ('王五', '40')
这里 groups()
返回了一个包含所有匹配的元组,分别是姓名和年龄。
(五)反向引用分组
-
正则表达式允许在匹配时引用前面匹配到的分组内容。这通常用于验证某些内容的重复,例如匹配重复的字符或词组。
-
反向引用的语法是
\1
,\2
等,其中数字表示对应的分组。
示例:匹配重复的单词
import re
text = "hello hello world"
# 使用反向引用匹配重复的单词
pattern = r"(\b\w+\b)\s+\1"
result = re.search(pattern, text)if result:print(result.group()) # 输出: hello hello
在这个例子中,(\b\w+\b)
匹配了一个单词,\1
引用了第一个分组的内容,从而匹配重复的单词。
(六)分组嵌套
分组可以嵌套使用,内层的分组优先级高,嵌套的分组也会有索引。
示例:嵌套分组
import re
text = "I have 2 apples and 3 oranges."
# 匹配数量和水果类型,使用嵌套分组
pattern = r"(\d+) (apples|oranges)"
result = re.findall(pattern, text)
print(result) # 输出: [('2', 'apples'), ('3', 'oranges')]
在这个例子中,外层分组 (\d+)
匹配数量,内层分组 (apples|oranges)
匹配水果类型,最终通过 findall()
返回所有匹配项。
(七)忽略大小写和多行分组匹配
如果想在分组匹配时忽略大小写或处理多行匹配,可以使用 re.IGNORECASE
和 re.MULTILINE
等标志。
示例:忽略大小写的分组匹配
import re
text = "HELLO world"
# 使用 re.IGNORECASE 忽略大小写
pattern = r"(hello) (world)"
result = re.search(pattern, text, re.IGNORECASE)if result:print(result.groups()) # 输出: ('HELLO', 'world')
(八)匹配分组总结
分组在正则表达式中非常强大,既可以捕获匹配结果,也可以通过命名分组来提高代码的可读性。非捕获分组可以避免捕获不必要的信息,而反向引用则能够对重复内容进行验证。掌握分组的这些技巧可以极大增强正则表达式处理复杂文本的能力。
四、总结
正则表达式提供了一种简洁高效的方式来匹配和处理文本。本篇文章通过多个实际示例,展示了如何匹配多个字符、匹配字符串的开头和结尾,以及如何灵活运用分组来提取数据。在掌握了这些基本用法后,读者可以轻松应对各种复杂的文本处理任务。正则表达式虽然语法相对简洁,但功能极其强大。通过熟练运用分组、反向引用、命名分组等高级技巧,开发者可以显著提高代码的灵活性与可读性。
相关文章:

【Python爬虫实战】正则:多字符匹配、开头与结尾定位、分组技术详解
🌈个人主页:https://blog.csdn.net/2401_86688088?typeblog 🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、匹配多个字符 (一)匹配任意多个字符 ࿰…...

DOIP协议介绍-1
1.DOIP中的GID和EID是什么? 在DOIP(Diagnostics over IP)中,GID(Group Identification)和EID(Entity Identification)是两个重要的标识符,它们各自承担着不同的角色和功…...

探索Python中的多线程与多进程
在Python编程中,多线程和多进程是两个重要的概念,它们被用来提高程序的执行效率。本文将深入探讨这两个概念,并对比它们在Python中的实现方式。 一、多线程 多线程是一种并发执行的程序设计方法。在Python中,我们可以使用thread…...

paypal php 实现详细攻略
一、准备工作 登录 https://www.paypal.com/ 注册一个主账号(选择个人账号、企业账后都可) 申请完成后登录https://developer.paypal.com/ 在后台右侧菜地点击“Accounts”,可以看到系统自动给分配的两个沙箱环境的账号。类型为Personal是个人…...

深入理解Dubbo原理鱼实现,提升职场竞争力
小熊学Java全能学习面试指南:https://www.javaxiaobear.cn 1、RPC RPC(Remote Procedure Call)远程过程调用,它是一种通过网络从远程计算机程序上请求服务。 大白话理解就是:RPC让你用别人家的东西就像自己家的一样。 RPC两个作用࿱…...

自动化测试与敏捷开发的重要性
敏捷开发与自动化测试是现代软件开发中两个至关重要的实践,它们相互补充,共同促进了软件质量和开发效率的提升。 敏捷开发的重要性 敏捷开发是一种以人为核心、迭代、循序渐进的软件开发方法。它强调以下几个核心价值观和原则: 个体和交互…...

气膜:冰雪产业的创新解决方案—轻空间
随着冰雪运动的普及和发展,如何在不同季节和地区有效开展冰雪项目,成为了行业内的一个重要课题。气膜作为一种新兴的建筑形式,凭借其独特的优势,正在逐渐成为冰雪产业的创新解决方案。 优越的建筑特性 气膜建筑以其轻便、快速搭建…...

期货配资网/分仓多元化/配资系统服务商
提供期货配资服务的网络平台搭建服务。这些平台致力于为投资者提供高效、便捷的期货投资渠道,通过配资的方式放大投资者的资金杠杆,从而增加其盈利机会。期货配资网一般具有以下特点: 专业服务:提供期货交易、投资管理及信息咨询…...

「漏洞复现」百易云资产管理运营系统 ufile.api.php SQL注入漏洞
0x01 免责声明 请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。工具来自网络,安全性自测,如有侵权请联系删…...

Vue 3 和 Vue Router 使用 createWebHistory 配置
在 Vue 3 项目中,如果使用 Vue Router 并希望启用 HTML5 History 模式,需要在创建路由器实例时传入 createWebHistory 作为历史模式的配置。此外,还需要确保在生产环境中设置正确的基本路径(base),这样才能…...

Nginx:rewrite指令之flag标志
Nginx 的 rewrite 指令用于根据正则表达式来匹配请求的 URI,并将其重写为新的 URI。rewrite 指令可以包含一个可选的 flag(标志),该标志用于控制重写操作后的行为。 rewrite regex replacement [flag] 一. 常用四种 flag redir…...

C#从零开始学习(如何构建应用)
开始使用 C# 开发使用的软件Visual Studio 2019 文章所有的代码都放在 https://github.com/hikinazimi/head-first-Csharp 创建一个控制台应用 打开Visual Studio 2019 创建项目 选择控制台应用程序 创建后点击运行,就可以在控制台打印Hello World 构建一个游戏(创建WPF项目…...

FCoE简介
数据中心融合网络的发展趋势 如图1所示,传统数据中心组网中,以太网LAN(Local Area Network)用于服务器与服务器、客户端与服务器之间通信,存储区域网络SAN(Storage Area Network)用于服务器与存…...

论文笔记:Template-Based Named Entity Recognition Using BART
论文来源:ACL 2021 Finding 论文链接:https://aclanthology.org/2021.findings-acl.161.pdf 论文代码:GitHub - Nealcly/templateNER: Source code for template-based NER 笔记仅供参考,撰写不易,请勿恶意转载抄袭…...

【Nestjs】从入门到精通(依赖注入)
NestJS 是一个基于 Node.js 的渐进式框架,构建在 Express 或 Fastify 之上,主要用于构建高效、可扩展的服务器端应用程序。它使用 TypeScript 并借鉴了 Angular 的设计理念,采用了依赖注入(IoC, Inversion of Control)…...

C语言函数
1.C语言函数的定义 C源程序是由函数组成的。最简单的程序有一个主函数main(),但实用程序往往由多个函数组成,由主函数调用其他函数,其他函数也可以互相调用。函数是C源程序的基本模块,程序的许多功能是通过对函数模块的调用来实现…...

FLINK SQLTable API 的基本概念及常用API
基本概念 SQL和Table API是Apache Flink提供的两个关系型API,它们被设计用于统一的流和批处理。以下是关于SQL和Table API的基本概念及常用API的详细介绍: 一、基本概念 Table API 定义:Table API是一个为Java、Scala和Python提供的语言集…...

Docker daemon.json配置参数及格式帮助信息
我们知道程序运行,通过修改命令参数或者配置文件配置项,对程序进行修改。Docker也不例外,通过docker.service 增加命令参数或者在/etc/docker/daemon.json中增加配置项均可。 推荐修改daemon.json对docker守护进程进行配置更改(方…...

十月编程语言排行榜~
前言:TIOBE编程语言排行榜通过分析全球开发者的活动、代码搜索和问答社区的流量,提供了编程语言受欢迎度的动态图景。该指数是技术趋势的风向标,揭示了哪些编程语言在技术领域占据主导地位,哪些语言正在快速崛起或逐渐衰退。 ✨✨…...

十三、行为型(策略模式)
策略模式(Strategy Pattern) 概念 策略模式(Strategy Pattern)是一种行为型设计模式,允许定义一系列算法,将每个算法封装在策略类中,并使它们可以互换使用。客户端可以根据需要动态选择不同的策…...

Vue环境安装以及配置
这里写目录标题 前言一、前置要求1.安装Node.js2. 安装VScode 二、创建全局安装目录和缓存日志目录三、配置环境变量四、权限五、npm换源六、vscode插件1. Vue-Offical2. Vue 3 Snippets3. Path Intellisense4. Auto Import5. Auto Close Tag6. Auto Rename Tag7.GitLens总结 前…...

Redis 数据类型hash(哈希)
目录 1 基本特性 2 主要操作命令 2.1 设置和获取字段 2.1.1 HSET key field value 2.1.2 HGET key field 2.1.3 HMSET key field1 value1 [field2 value2 ...] 2.1.4 HMGET key field1 [field2 ...] 2.2 检查字段是否存在 2.2.1 HEXISTS key field 2.3 获取所有字段…...

单一执行和循环执行的例行性工作
单一执行的例行性工作:只执行一次就结束 1.1at命令的工作过程 /etc/at.allow,写在该文件的人可以使用at命令 /etc/at.deny,黑名单 两个文件如果都不存在,只有root能使用 [rootlocalhost ~]# systemctl status atd [rootlocalh…...

单细胞分析 | Cicero+Signac 寻找顺式共可及网络
引言 在本指南[1]中,将介绍如何利用Cicero工具和单细胞ATAC-seq数据来识别共可接近网络。 为了在Seurat(Signac工具使用的格式)和CellDataSet(Cicero工具使用的格式)之间轻松转换数据,将利用GitHub上的Seur…...

人工智能创造出大量新型蛋白质
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

Palo Alto Networks Expedition 未授权SQL注入漏洞复现(CVE-2024-9465)
0x01 产品介绍: Palo Alto Networks Expedition 是一款强大的工具,帮助用户有效地迁移和优化网络安全策略,提升安全管理的效率和效果。它的自动化功能、策略分析和可视化报告使其在网络安全领域中成为一个重要的解决方案。 0x02 漏洞描述&am…...

c 语言 sprintf
在C语言中,sprintf是一个非常常用的函数,它用于将格式化的数据写入字符串中。sprintf函数的原型通常定义在stdio.h头文件中。 sprintf函数的原型如下: int sprintf(char *str, const char *format, …); 参数说明: str…...

stm32单片机个人学习笔记10(TIM编码器接口)
前言 本篇文章属于stm32单片机(以下简称单片机)的学习笔记,来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记,只能做参考,细节方面建议观看视频,肯定受益匪浅。 STM32入门教程-2023版 细…...

如何在Android中存储数据?
在Android中存储数据是开发过程中至关重要的一环,根据数据的类型、大小、访问频率及安全性需求,开发者可以选择多种存储方式。以下是Android中存储数据的几种主要方式,每种方式都有其特定的应用场景和优缺点。 一、SharedPreferences Share…...

13.3寸工业三防平板数字化工厂产线数采手持终端
在数字化工厂的建设浪潮中,高效可靠的数据采集终端至关重要。尤其在水处理、食品加工等特殊工业环境下,设备的耐用性和数据安全性面临严峻挑战。传统的平板电脑难以应对复杂的工业现场,而一款性能卓越、坚固耐用的工业三防平板则成为提升生产…...