python爬虫 - 深入正则表达式

news2024/11/25 2:38:17

  🌈个人主页: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/2205400.html

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

相关文章

Java学习-JVM

目录 1. 基本常识 1.1 JVM是什么 1.2 JVM架构图 1.3 Java技术体系 1.4 Java与JVM的关系 2. 类加载系统 2.1 类加载器种类 2.2 执行顺序 2.3 类加载四个时机 2.4 生命周期 2.5 类加载途径 2.6 双亲委派模型 3. 运行时数据区 3.1 运行时数据区构成 3.2 堆 3.3 栈…

adaptor lora基础

https://www.zhihu.com/question/508658141/answer/3340979311 adaptor和PEFT的区别&#xff1a;前者在模型子层后加一个小型的dense&#xff1b;后者直接稀疏化模型本身&#xff1b; Loading Pre-Trained Adapters — AdapterHub documentation CVPR 2024 | SD-DiT&#xff…

五分钟带你零基础入门跨境电商独立站,干货速递!

对于跨境电商卖家来说&#xff0c;多平台、多站点的布局是非常重要的战略。这样做可以规避”鸡蛋放在同一个篮子里”的风险也能够追求更高的销售额和利润。同时&#xff0c;市场的变化也带来了新的发展机会&#xff0c;因此很多出海企业都希望抓住独立站的新机遇&#xff0c;抢…

什么因素能冲击实时现货黄金价格?

实时现货黄金价格怎样走&#xff0c;投资者关键要看全球通胀、经济增长、美联储货币政策和全球央行需求这些基本面的因素。在全球货币体系“去美元化”趋势越来越明晰的当下&#xff0c;黄金在国际储备中的地位将逐步上升——在尚未出现可取代美元的货币之前&#xff0c;黄金独…

电机是怎么转起来的?

世界上功率消耗量的近一半是由电机消耗&#xff0c;因此在解决世界能源问题上&#xff0c;电机的高效率化被称为是最有效的措施。 电机种类 一般情况下指将磁场内电流流通产生的力转变为旋转动作&#xff0c;在广义范围内还包括直线动作。 按电机驱动的电源种类&#xff0c;…

QD1-P17 HTML常用标签:下拉框

本节学习 HTML 常用标签&#xff1a;select和option ‍ 本节视频 www.bilibili.com/video/BV1n64y1U7oj?p17 ‍ 知识点1&#xff1a;select标签用法 演示 ​​ HTML <select name"city"><option>北京</option><option>上海</opti…

【计网】从零开始学习http协议 ---深入理解cookie和session

我的天空里没有太阳&#xff0c; 总是黑夜&#xff0c; 但并不暗&#xff0c; 因为有东西代替了太阳。 --- 东野圭吾 --- 从零开始学习http协议 1 理解cookie1.1 什么是cookie1.2 验证cookie1.3 cookie的属性 2 理解session2.1 什么是session2.2 验证session 1 理解cooki…

考研笔试/上机经典编程题集合(持续更新并完善解题思路)

目录 一、程序设计经典编程题(C语言实现)1.1 判断一个字符串是否由另一个字符串旋转得到1.2 字符串左旋1.3 求最大公约数以及最小公倍数1.4 二、力扣2.1 面试题 17.04. 消失的数字 三、牛客网3.1 OR62 倒置字符串3.2 BC84 计算y的值 一、程序设计经典编程题(C语言实现) 1.1 判…

Java生成csv格式文件样例_快速详细

Java高效Excel处理工具EasyExcel&#xff1a;解决大文件读写难题 EasyExcel是一个基于Java的高效、简洁的Excel处理工具&#xff0c;专为解决大文件内存溢出问题而设计。它能够在不牺牲性能的前提下快速完成Excel文件的读写操作。相比于传统的Apache POI等框架&#xff0c;Eas…

Unity修改鼠标图片【超简单】

1.向Unity导入需要修改的鼠标图片&#xff0c;在Unity内设置图片的Texture Type为Cursor。 2.编写代码 [SerializeField] Texture2D mouseTex;//放图片 void Start() {Cursor.SetCursor(mouseTex, Vector2.zero, CursorMode.Auto); }3.代码挂载在某物体&#xff08;或者随便哪…

net ASp.net Core 文件上传 IFormFile IFormFileCollection

IFormFile 接口是 ASP.NET Core 中处理上传文件的标准方式。当客户端通过表单上传文件时&#xff0c;ASP.NET Core 会自动将上传的文件封装成一个 IFormFile 对象&#xff0c;然后你可以在服务器端通过这个对象来访问和处理文件。 IFormFile接口的使用场景包括但不限于&…

java:找不到符号符号: 变量 log解决方案

最近有个项目频繁的遇到这个问题.经常启动不起来,但是提代码正常. 这个问题是由于lombok插件未加载导致的Slf4j的日志异常. 解决思路: 1.插件里面写在lombok再重新安装.无效 2.重新加载项目.无效 3.重新构建项目.无效 4.删除代码重下代码.无效 5.检查该配置是否打开,已打开 6.…

离散数学-逻辑与证明基础1.3(命题等价)

介绍 定义 1 一个复合命题&#xff0c;如果无论其中命题变量的真值如何&#xff0c;它总是为真&#xff0c;则称为重言式&#xff08;tautology&#xff09;。一个复合命题&#xff0c;如果它总是为假&#xff0c;则称为矛盾式&#xff08;contradiction&#xff09;。一个既不…

JDK11~JDK17值得关注的更新整理

新增特性&#xff1a; 1、instanceof的模式匹配 (JDK 16) 这个特性增强了instanceof运算符&#xff0c;允许在检查一个对象的类型时直接进行模式匹配&#xff0c;这使得代码更加简洁和易于理解。 通常我们使用instanceof时&#xff0c;一般发生在需要对一个变量的类型进行判…

QT C++ 软键盘/悬浮键盘/触摸屏键盘的制作

目录 1、前言 2、界面设计 3、英文、数字的输入 4、符号的输入 5、中文的输入 6、中文拼音库的选择 7、其他 8、结语 1、前言 使用QT C在带显示器的Linux系统 开发板上&#xff08;树莓派等&#xff09;编写操作UI界面时&#xff0c;很多时候都需要一个软键盘来输入文字…

施工进度可视化:提升项目管理透明度

图扑施工可视化通过直观的数据展示&#xff0c;使项目各方能够实时了解进度和资源分配&#xff0c;识别潜在问题&#xff0c;提高沟通效率&#xff0c;优化决策流程&#xff0c;确保项目按时、高效、安全地推进。

22个IT运维领域黄金证书 每一个都含金量极高!

**1、阿里云认证&#xff1a;**阿里云提供多个层次的认证&#xff0c;包括ACA&#xff08;助理工程师&#xff09;、ACP&#xff08;专业工程师&#xff09;和ACE&#xff08;专家工程师&#xff09;&#xff0c;涵盖了云计算、大数据、云安全、人工智能等多个领域。 **2、ITS…

【text2sql】基于上下文文学习的MCS-SQL框架在Spider和BIRD取得了新SOTA

论文标题 “MCS-SQL: Leveraging Multiple Prompts and Multiple-Choice Selection For Text-to-SQL Generation” &#xff0c;发表于2024.5的arXiv。 1.摘要解读 研究背景&#xff1a;大型语言模型&#xff08;LLMs&#xff09;在文本到SQL&#xff08;Text-to-SQL&#xf…

Python中的help()函数引发错误:追踪错误并提供解决方案

Python 中的 help() 函数通常用于交互式帮助&#xff0c;它可以显示关于模块、类、函数、方法、关键字等的文档说明。一般情况下&#xff0c;help() 函数不会引发错误&#xff0c;但如果你在使用时遇到问题&#xff0c;可能与以下几种常见情况有关。 1、问题背景 在使用 Pytho…

宝藏推荐:精选十款知识库搭建软件

当今这个信息爆炸的时代&#xff0c;高效地管理和利用知识成为了各行各业追求的目标。无论是企业内部的协作&#xff0c;还是对外提供的信息服务&#xff0c;一个强大的知识库都是不可或缺的。为了帮助大家更好地守护和利用知识宝藏&#xff0c;以下是精选的十款知识库搭建软件…