【Python爬虫实战】正则:多字符匹配、开头与结尾定位、分组技术详解

ops/2024/10/15 8:50:40/

  🌈个人主页: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次或多次。

示例:

python">import re
text = "hello world"
result = re.findall(r'.*', text)
print(result)  # 输出: ['hello world', '']

(二)匹配一个或多个字符

使用 + 匹配前面的字符一次或多次,保证至少匹配一个字符。

示例:

python">import re
text = "abc123"
result = re.findall(r'\d+', text)
print(result)  # 输出: ['123']

(三)匹配特定数量的字符

  • 使用 {n} 来精确匹配前面的字符 n 次。

  • 使用 {n,m} 来匹配前面的字符至少 n 次,至多 m 次。

示例:

python">import re
text = "12345"
# 匹配恰好5个数字
result = re.findall(r'\d{5}', text)
print(result)  # 输出: ['12345']

(四)匹配字符范围

使用字符集 [] 匹配多个特定字符,或者使用字符范围(如 [a-z])来匹配多个连续字符。

示例:

python">import re
text = "abcdef123"
result = re.findall(r'[a-f]+', text)  # 匹配a-f范围内的多个字符
print(result)  # 输出: ['abcdef']

(五)匹配非数字、非字母等

使用反向匹配 [^] 来匹配多个不属于某类的字符。例如,[^0-9]+ 匹配非数字的字符序列。

示例:

python">import re
text = "abc123def"
# 匹配非数字的字符序列
result = re.findall(r'[^0-9]+', text)
print(result)  # 输出: ['abc', 'def']

(六)使用 re.DOTALL 匹配多行

使用 re.DOTALL 标志符,使 . 能够匹配包括换行符在内的所有字符,通常用于匹配跨多行的文本。

示例:

python">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 结尾的字符串。

示例:

python">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+ 匹配多个空白字符(如空格、制表符、换行符)。

示例:

python">import re
text = "abc 123"
# 匹配多个字母或数字
result = re.findall(r'\w+', text)
print(result)  # 输出: ['abc', '123']# 匹配多个空格
result = re.findall(r'\s+', text)
print(result)  # 输出: [' ']

(九)匹配多个字符总结

正则表达式可以通过使用量词、字符集和特殊符号来匹配多个字符。无论是匹配任意字符、特定字符、字符集,还是根据字符出现次数来匹配,正则表达式都可以提供灵活和强大的解决方案。熟练掌握这些技巧后,你可以有效处理多种文本处理需求。


二、匹配开头和结尾

在正则表达式中,使用 ^$ 分别可以匹配字符串的开头和结尾。它们的具体用法如下:

(一)匹配字符串的开头:^

^ 用于匹配字符串的开头。只有当字符串以指定的模式开头时,才会匹配成功。

示例: 假设我们想匹配以 "hello" 开头的字符串:

python">import re
text = "hello world"
result = re.findall(r'^hello', text)
print(result)  # 输出: ['hello']

如果字符串不是以 "hello" 开头,则匹配会失败:

python">text = "world hello"
result = re.findall(r'^hello', text)
print(result)  # 输出: []

(二)匹配字符串的结尾:$

$ 用于匹配字符串的结尾。只有当字符串以指定的模式结尾时,才会匹配成功。

示例: 假设我们想匹配以 "world" 结尾的字符串:

python">import re
text = "hello world"
result = re.findall(r'world$', text)
print(result)  # 输出: ['world']

如果字符串不是以 "world" 结尾,则匹配会失败:

python">text = "world hello"
result = re.findall(r'world$', text)
print(result)  # 输出: []

(三)同时匹配开头和结尾

可以结合 ^$ 同时使用,来匹配整个字符串的模式。例如,匹配完整的字符串 "hello world"

python">import re
text = "hello world"
result = re.findall(r'^hello world$', text)
print(result)  # 输出: ['hello world']

示例

python">import re
text = "hello world"
result = re.findall(r'^hello world$', text)
print(result)  # 输出: ['hello world']

这个模式要求整个字符串必须是 "hello world",否则匹配不会成功:

python">text = "hello world!"
result = re.findall(r'^hello world$', text)
print(result)  # 输出: []

(四)匹配多行模式

默认情况下,^$ 只会匹配整个字符串的开头和结尾。如果要在多行字符串中分别匹配每一行的开头和结尾,可以使用 re.MULTILINE 标志。

示例

python">import re
text = """hello world
goodbye world"""
# 匹配每行的开头为 'hello' 或 'goodbye'
result = re.findall(r'^(hello|goodbye)', text, re.MULTILINE)
print(result)  # 输出: ['hello', 'goodbye']

在这种情况下,^$ 会作用于每一行的起始和结束位置,而不仅仅是整个字符串的起始和结束。

(五)示例:验证电子邮件

假设我们需要验证电子邮件地址的格式,要求它以字母或数字开头,包含 @,并以域名结尾。可以结合 ^$ 来确保整个字符串符合电子邮件格式:

python">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() 方法来获取匹配的分组内容。

示例:匹配并提取姓名和年龄

python">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 是分组的名字。

示例:使用命名分组提取姓名和年龄

python">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

在这种方式下,你可以通过分组的名称 nameage 来提取匹配的内容,代码更加清晰。

(三)非捕获分组

有时我们只想对表达式进行分组,而不希望捕获这个分组的匹配结果。可以使用 (?:...) 来创建一个非捕获分组。这样该分组参与匹配,但不会出现在匹配的结果中。

示例:使用非捕获分组

python">import re
text = "apple, banana, cherry"
# 使用非捕获分组来匹配不同的水果
pattern = r"(?:apple|banana|cherry)"
result = re.findall(pattern, text)
print(result)  # 输出: ['apple', 'banana', 'cherry']

在这个例子中,(?:...) 只是用来匹配,但不会被作为分组结果提取。

(四)使用 groups() 提取所有分组

使用 groups() 可以一次性提取所有分组的匹配内容,返回的是一个包含所有分组内容的元组。

示例:提取所有分组内容

python">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 等,其中数字表示对应的分组。

示例:匹配重复的单词

python">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 引用了第一个分组的内容,从而匹配重复的单词。

(六)分组嵌套

分组可以嵌套使用,内层的分组优先级高,嵌套的分组也会有索引。

示例:嵌套分组

python">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.IGNORECASEre.MULTILINE 等标志。

示例:忽略大小写的分组匹配

python">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')

(八)匹配分组总结

分组在正则表达式中非常强大,既可以捕获匹配结果,也可以通过命名分组来提高代码的可读性。非捕获分组可以避免捕获不必要的信息,而反向引用则能够对重复内容进行验证。掌握分组的这些技巧可以极大增强正则表达式处理复杂文本的能力。


四、总结

正则表达式提供了一种简洁高效的方式来匹配和处理文本。本篇文章通过多个实际示例,展示了如何匹配多个字符、匹配字符串的开头和结尾,以及如何灵活运用分组来提取数据。在掌握了这些基本用法后,读者可以轻松应对各种复杂的文本处理任务。正则表达式虽然语法相对简洁,但功能极其强大。通过熟练运用分组、反向引用、命名分组等高级技巧,开发者可以显著提高代码的灵活性与可读性。


http://www.ppmy.cn/ops/125856.html

相关文章

buffer/cache内存优化_posix_fadvise_主动释放读缓存cache

1.问题现象 1.htop free命令发现系统 buffer/cache 内存占用高 free -h total used free shared buff/cache available Mem: 61Gi 15Gi 569Mi 1.7Gi 45Gi 43Gi Swap: 30Gi 0.0Ki 30Gi cat /proc/meminfo or grep -E "Buff|Cache" /proc/meminfo Buffers: 370568 kB …

Postman最新V11版本关键更新一览

Postman作为接口测试中&#xff0c;被广泛应用的一款主流工具&#xff0c;以其丰富的功能&#xff0c;灵活方便的使用方式&#xff0c;广受欢迎。最新发布的V11版本则在向协作平台转型的过程中一路狂奔&#xff0c;增加大量全新的协作支持。下面我们就一起来看看都有哪些变化吧…

戴尔Windows10专业版系统镜像:免费获取!

今天&#xff0c;系统之家小编给大家分享2024年最新的戴尔Windows10专业版系统下载&#xff0c;该版本系统采用最新Windows10 22H2 19045.5011 64位专业版进行离线制作&#xff0c;确保系统安全无毒&#xff0c;系统的一些安全问题也得到解决&#xff0c;整体操作更放心。系统的…

adminPage-vue3依赖 v1.2.0新增组件 DetailsModule说明文档

adminPage-vue3依赖 v1.2.0新增组件 DetailsModule说明文档 引入思路介绍DetailsModuleAPI汇总属性插槽自定义对象config(array<object\>/object 类型)config.list(array<object\> 类型) 使用基础使用范例config-titleconfig-moduleKeyconfig-listconfig-list-slot…

【Oracle 数据库技术分享】BLOB 与 CLOB 的选择与应用

【Oracle 数据库技术分享】BLOB 与 CLOB 的选择与应用 文章目录 前言一、为什么选择 BLOB 或 CLOB&#xff1f;二、BLOB 与 CLOB 的区别1.数据类型2.性能3.功能4.兼容性5.存储限制6.查询和处理 三、选择 BLOB 或 CLOB 的建议1.根据数据类型选择2.考虑性能需求3.兼容性和集成4.综…

数据结构——递归思想

递归思想是一种在数学和计算机科学中广泛应用的解决问题的方法。它的核心思想是将一个复杂的问题分解为规模较小的相同类型的问题&#xff0c;直到达到一个可以直接解决的简单情况&#xff08;通常称为基准情况或递归终止条件&#xff09;。递归通过函数调用自身来实现这一分解…

Spring Cloud Sentinel配置

Spring Cloud Sentinel 文章目录 Spring Cloud Sentinel1. Sentinel Dashboard 启动2. Spring Cloud 客户端配置3. Sentinel Dashboard 限流配置直连关联链路 4. Sentinel Dashboard 熔断配置 1. Sentinel Dashboard 启动 下载sentinel dashboard jar包sentinel dashboard启动…

MES管理系统如何实现生产过程全流程追溯

在现代制造业的转型升级中&#xff0c;MES管理系统作为核心管理工具&#xff0c;正以其卓越的能力引领着生产过程的实时追踪与优化。MES管理系统通过一系列创新技术和精细化管理模块&#xff0c;构建了一个高度集成、高效运转的生产监控平台&#xff0c;为企业提供了前所未有的…