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

news2025/1/12 22:52:10

  🌈个人主页: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

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

(三)非捕获分组

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

示例:使用非捕获分组

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.IGNORECASEre.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')

(八)匹配分组总结

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


四、总结

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

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

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

相关文章

OpenAI Canvas:提升编程与写作效率的全新工作界面

随着人工智能技术的飞速发展&#xff0c;大语言模型&#xff08;LLM&#xff09;不仅限于生成文本&#xff0c;还能逐步扩展至编程、设计等任务的支持。近期&#xff0c;OpenAI 推出了一个名为 Canvas 的全新功能&#xff0c;专门用于协助用户进行编程和写作。这一功能与 Claud…

请求参数中字符串的+变成了空格

前端请求 后端接收到的结果 在URL中&#xff0c;某些字符&#xff08;包括空格、、&、? 等&#xff09;需要被编码。具体而言&#xff0c;在URL中&#xff0c;空格通常被编码为 或 %20。因此&#xff0c;如果你在请求参数中使用 &#xff0c;它会被解释为一个空格。 如果…

C++ | Leetcode C++题解之第473题火柴拼正方形

题目&#xff1a; 题解&#xff1a; class Solution { public:bool makesquare(vector<int>& matchsticks) {int totalLen accumulate(matchsticks.begin(), matchsticks.end(), 0);if (totalLen % 4 ! 0) {return false;}int len totalLen / 4, n matchsticks.s…

lstm和informer和gru模型对比

1 介绍 本文使用数据集&#xff0c;对三个模型进行了对比&#xff0c;代码使用python完成&#xff0c;通过对比&#xff0c;发现lstm>gru>informer. 2 数据读取 使用降水量数据集&#xff0c;第一列表示降水&#xff0c;第二列表示出水量。 输入是两个特征输出是一个…

百度视觉搜索架构演进实践

本文深入探讨百度视觉搜索在快速发展的业务及技术背景下&#xff0c;如何通过持续的技术创新和架构升级强化自身的竞争力和适应性&#xff0c;支撑业务健康高效迭代。本文介绍了我们如何通过技术栈升级、架构能力提升以及稳定性建设&#xff0c;来实现全链路架构的演进。借助Go…

MySQL 9从入门到性能优化-二进制日志

【图书推荐】《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;》-CSDN博客 《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;&#xff08;数据库技术丛书&#xff09;》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) MySQL9数据库技术_夏天又到了…

matlab输入汉字时,输入法在左上角显示解决办法

解决方法&#xff1a; 输入汉字时输入法在左上角显示&#xff08;如图1&#xff09;&#xff0c;将鼠标放在竖着的小点处拖动到工作区合适位置&#xff08;如图2&#xff09;&#xff0c;下次输入汉字时输入法便在图2处显示。 图1 图2

前端小技巧-网页点击动画效果

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><title>点击触发动画效果</title><link rel"stylesheet" href"styles.css" /></head><style>/* styles.css */…

【C++ 贪心 滑动窗口 前后缀分解】948. 令牌放置|1762

本文涉及的基础知识点 贪心 决策包容性 C算法&#xff1a;滑动窗口及双指针总结 反向双指针 C前后缀分解 LeetCode948. 令牌放置 你的初始 能量 为 power&#xff0c;初始 分数 为 0&#xff0c;只有一包令牌以整数数组 tokens 给出。其中 tokens[i] 是第 i 个令牌的值&…

C语言 | Leetcode C语言题解之第473题火柴拼正方形

题目&#xff1a; 题解&#xff1a; bool makesquare(int* matchsticks, int matchsticksSize) {int totalLen 0;for (int i 0; i < matchsticksSize; i) {totalLen matchsticks[i];}if (totalLen % 4 ! 0) {return false;}int len totalLen / 4, n matchsticksSize;i…

【实战经验】互联网信息服务域名注册和备案-指导指南 v2

一、业务场景 个人/企业/组织&#xff08;ICP&#xff09;在提供互联网信息服务&#xff08;例&#xff1a;开通网站、小程序&#xff09;之前&#xff0c;应当向为其接入互联网服务的互联网服务提供商&#xff08;ISP&#xff09;&#xff08;腾讯、阿里云&#xff09;提交相关…

【JavaEE初阶】深入透析文件-IO关于文件内容的操作(四种文件流)

前言 &#x1f31f;&#x1f31f;本期讲解关于CAS的补充和JUC中有用的类&#xff0c;这里涉及到高频面试题哦~~~ &#x1f308;上期博客在这里&#xff1a;【JavaEE初阶】文件-IO之实现文件系统的操作如何进行实现-CSDN博客 &#x1f308;感兴趣的小伙伴看一看小编主页&…

初识算法 · 滑动窗口(3)

目录 前言&#xff1a; 水果成篮 题目解析 算法原理 算法编写 找到字符串中所有字符异位词 题目解析 算法原理 算法编写 前言&#xff1a; ​本文的主题是滑动窗口&#xff0c;通过两道题目讲解&#xff0c;一道是水果成篮&#xff0c;一道是找到字符串中的所有字母异…

(Linux驱动学习 - 11).Input 子系统

一.Input 子系统的定义 input 就是输入的意思&#xff0c;因此 input 子系统就是管理输入的子系统&#xff0c;和 pinctrl、 gpio 子系统 一样&#xff0c;都是 Linux 内核针对某一类设备而创建的框架。比如按键输入、键盘、鼠标、触摸屏等 等这些都属于输入设备&#xff0c;不…

聊聊 Facebook Audience Network 绑定收款账号的问题

大家好&#xff0c;我是牢鹅&#xff01;本篇是Facebook开发者系列的第五篇&#xff0c;最近看见好多群友在群里问这个&#xff0c;说Facebook的变现账户在绑定国内的银行账户时&#xff08;有些用户反馈就算不是国内的卡也会出现该问题&#xff09;&#xff0c;显示“无法绑定…

05 django管理系统 - 部门管理 - 修改部门

04我们已经实现了新增部门的功能&#xff0c;下面开始修改部门模块的实现。 按道理来说&#xff0c;应该是做成弹框样式的&#xff0c;通过ajax悄咪咪的发数据&#xff0c;然后更新前端数据&#xff0c;但是考虑到实际情况&#xff0c;先用页面跳转的方式实现&#xff0c;后面…

【含文档】基于Springboot+Vue的旅游信息管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

QSettings 使用详解

QSettings 类是 Qt 框架中的一个重要类&#xff0c;用于存储和访问应用程序的设置和配置。它提供了一种简单的方法来读取和写入应用程序的配置数据&#xff0c;支持多种存储格式&#xff0c;包括 Windows 注册表、INI 文件和 XML 文件等。 主要功能 1. 存储设置&#xff1a;可…

PDF在线编辑器推荐!一站式解决PDF编辑难题!

当你要对PDF文件进行编辑时&#xff0c;一款PDF编辑器就十分重要。今天小编就为大家推荐几款PDF编辑器&#xff0c;有在线的&#xff0c;也有本地的&#xff0c;大家可以根据自己的需求体验选择&#xff01; Foxit PDF Edit 直达链接&#xff1a;editor.foxitsoftware.cn Fo…

大舍传媒-海外媒体发稿:为您打造全球品牌影响力

大舍传媒-海外媒体发稿&#xff1a;为您打造全球品牌影响力 在当今全球化的商业环境中&#xff0c;企业若想在激烈的市场竞争中脱颖而出&#xff0c;拓展全球市场&#xff0c;提升品牌影响力至关重要。大舍传媒的海外媒体发稿服务&#xff0c;正是您实现这一目标的得力助手。 …