Python 正则表达式学习笔记

本文详细介绍正则表达式的各种实用方法,如match、search、findall等,并讲解了贪婪与非贪婪模式的区别及应用。此外,还介绍了如何通过分组来精确提取所需信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

match() 和 search() 的不同

import re
# 注意:要从字符串的起始位置开始匹配
m = re.match("foo","my foo on the table")
if m is not None:
    print(m.group())
else:
    print("没有找到匹配的元素")

控制台打印:没有找到匹配的元素

import re
# 搜索的模式出现在一个字符串中间
m = re.search('foo','my foo on the table')
if m is not None:
    print(m.group())
else:
    print("没有找到匹配的元素")

控制台打印:foo

import re

m = re.search('foo', 'seafood')
if m is not None: print(m.group())

控制台打印:foo

方法 match()

import re
bt = 'bat|bet|bit'
m = re.match(bt,'bat')
if m is not None:
    print(m.group())

控制台打印:bat。
说明:在没有括号的情况下,使用 m.group() 得到返回。

import re

haRegex = re.compile('(Ha){3,5}')
mo1 = haRegex.search('bbbHaHaHaHaHabbb')
print(mo1.group())
# 不加问号,是贪心模式,匹配最多
# HaHaHaHaHa


haRegex = re.compile('(Ha){3,5}?')
mo1 = haRegex.search('bbbHaHaHaHaHabbb')
print(mo1.group())
# 还可以在花括号后面加上问号,表示非贪心的匹配
# HaHaHa

分隔符不一致的情况下,可以使用 re.split() 的方法。虽然字符串对象也提供了 split() 方法。

import re

line = 'asdf fjdk; afed, fjek,asdf,  foo'
list = re.split(r'[;,\s]\s*', line)
print(list)
# ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']

贪婪模式与非贪婪模式:

比较下面的两个例子:

.* 表示尽可能多地去匹配

import re

a = 'wxxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxxwuerowiur'
b = re.findall('xx.*xx', a)
print(b)
# 控制台打印:['xxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxx']

.*? 表示尽可能少地匹配

import re

a = 'wxxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxxwuerowiur'
b = re.findall('xx.*?xx', a)
print(b)
# 控制台打印:['xxIxx', 'xxlovexx', 'xxUxx']

这里写代码片

方法 findall

import re

relink = '<a href="(.*)">(.*)</a>'
info = '<a href="http://www.baidu.com">baidu</a>'
cinfo = re.findall(relink, info)

print(type(cinfo)) # <class 'list'>

print(cinfo[0]) # ('http://www.baidu.com', 'baidu')
print(cinfo[0][0]) # http://www.baidu.com
print(cinfo[0][1]) # baidu



import re

info = "abcd efg hij klmn"

# 不带有括号,其输出的内容就是整个表达式所匹配到的内容
regex1 = re.compile("\w+\s+\w+")
list1 = regex1.findall(info)
print(list1)

# 带有 1 个括号,其输出的内容就是括号匹配到的内容,而不是整个表达式所匹配到的结果。
regex2 = re.compile("(\w+)\s+\w+")
list2 = regex2.findall(info)
print(list2)

# 带有 3 个括号,我们可以看到其输出是一个 list 中包含 3 个 tuple
regex3 = re.compile("((\w+)\s+(\w+))")
list3 = regex3.findall(info)
print(list3)

结论:findall() 返回的是括号所匹配到的结果,多个括号就会返回多个括号分别匹配到的结果,如果没有括号就返回就返回整条语句所匹配到的结果。所以在提取数据的时候就需要注意这个坑。


如果一个正则表达式有分组,则 findall 方法返回 tuple 的列表。

findall_group_regex = re.compile(r'(\d{4})-(\d{2})-(\d{2})')
mo2 = findall_group_regex.findall('1987-07-06,1990-03-30,1987-03-20')
print(mo2)
# [('1987', '07', '06'), ('1990', '03', '30'), ('1987', '03', '20')]

findall() 找到所有匹配的方法,返回一组字符串(即字符串列表),包含被查找字符串中的所有匹配。

问号实现可选的匹配。

注意:问号在正则表达式中可能有两种含义:
1、声明非贪心的匹配
2、表示可选的分组

用星号匹配零次或者多次。

用加号匹配一次或者多次。

用花括号匹配特定的次数。

贪心和非贪心的匹配。

Python 的正则表达式默认是贪心的。这表示,在有“二义”的情况下,它们会尽可能地匹配最长的字符串。
在花括号的后面加上一个问号,即表示花括号的“非贪心”版本。

第 1 个参数是正则表达式

import re
a='xyz123'
# . 匹配任意一个字符
b = re.findall('x..',a) 
print(b)

[‘xyz’]

例:

import re

a = 'wxxIxxeuieiejfsdjxxlovexxfsiewiweirxxUxxwuerowiur'
b = re.findall('xx(.*?)xx', a)
print(b)
print(type(b))

for item in b:
    print(item)

控制台打印:

['I', 'love', 'U']
<class 'list'>
I
love
U

re.S

re.S 的作用是让 . 的作用包含了换行符 \n,这一点我们可以通过看 Python3 的源码得知

例:
请比较有 re.S 和没有 re.S 参数的不同:

import re

a = """rewixxhello
aaaaaaaxxuirwifdsfsdxxworldxxfkjsjke"""
b = re.findall("xx(.*?)xx", a, re.S)
print(b)

控制台打印:

['hello\naaaaaaa', 'world']

findall() 函数里面本身就有 compile() 方法。所以不用多此一举,先编译一下再使用。
使用 \d+ 表示纯数字。

这里写图片描述

Regex 的 search() 方法查找传入的字符串对象。
在 Python 中使用正则表达式的步骤:
1、import re
2、re.compile()
3、向 Regex 对象的 search() 方法中传入想查找的字符串,它返回一个 Match 对象。
4、调用 Match 对象的 group() 方法,返回实际匹配文本的字符串。

import re

phone_num_rex = re.compile(r'\d{3}-\d{4}-\d{4}')
mo = phone_num_rex.search('My Numver is 137-3062-9072')
print('Phone number found:' + mo.group())

print(type(mo.group()))

控制台打印:

Phone number found:137-3062-9072
<class 'str'>

说明:“\n” 表示一个换行符。

下面解释一下 re.compile(r'\d{3}-\d{4}-\d{4}') 的前面为什么要加上一个“r”。

通过在字符串的第一个引号之前加上 r ,可以将该字符串标记为原始字符串,它不包括转义字符。

正则表达式的分组

import re

# 分组得到的每一个元素是元组 tuple
findall_group_regex = re.compile(r'(\d{4})-(\d{2})-(\d{2})')
mo2 = findall_group_regex.findall('1987-07-06,1990-03-30,1987-03-20')
print(type(mo2))

for item in mo2:
    print(type(item))

控制台显示:

<class 'list'>
('1987', '07', '06')
('1990', '03', '30')
('1987', '03', '20')

利用括号分组

1、第 1 对括号就是第 1 组

2、向 group() 匹配对象方法传入整数 1 或者 2,就可以取得匹配文本的不同部分;

3、向 group() 匹配对象方法传入整数 0 或者 不传,就可以取得匹配文本的全部。

一次获取所有的分组,使用 groups() 方法,返回的是元组,所以,我们可以使用多重赋值的技巧。

元组还可以这样赋值:

a, b, c = (1, 2, 3)

print(a)
print(b)
print(c)

示例:

import re

dateStr = re.compile(r'(\d{4})-(\d{2})-(\d{2})')
mo = dateStr.search('1987-07-06')
# 是一个元组
print(type(mo.groups()))

year, month, day = mo.groups()
print(year)
print(month)
print(day)

字符的分类

\d: 0 到 9 的任何数字
\D: 除了 0 到 9 的数字以外的任何字符
\w: 任何字母、数字或者下划线字符(可以认为是匹配“单词”字符)
\W:
\s: 空格、制表符或者换行符(可以认为是匹配“空白”字符)
\S:

用 sub() 方法替换字符串。

### Python 正则表达式学习笔记 #### 1. 基本概念 正则表达式是一种用于匹配字符串中字符模式的强大工具。通过定义特定的语法结构,可以实现复杂的字符串搜索、替换等功能。 #### 2. 编译正则表达式对象 为了提高效率,在多次使用同一个模式时应该先将其编译成正则表达式对象。这可以通过 `re.compile()` 函数完成[^2]: ```python pattern = re.compile('www') matches = pattern.findall('www.baidu.www') # 结果为 ['www', 'www'] ``` #### 3. 使用特殊字符 某些字符具有特殊的含义,比如点号`.`表示任意单个字符(除换行符外)。如果想要匹配这些字符本身,则需要用反斜杠`\`来转义它们[^3]: ```python result = re.split(r'\.', "www.www.baidu.com") # 结果为 ['www', 'www', 'baidu', 'com'] ``` #### 4. 查找所有匹配项 函数 `findall()` 可以用来找到输入字符串中所有与给定模式相匹配的部分,并返回一个列表形式的结果集: ```python text = 'www.baidu.www' regex = re.compile('www') found_items = regex.findall(text) # 返回 ['www', 'www'] ``` #### 5. 实际应用案例 - 网页抓取 下面是一个简单的例子,展示了如何利用正则表达式从HTML文档中提取所需的信息。这里的目标是从指定URL页面内获取章节标题并打印出来[^4]: ```python import re import requests url = "https://example.com" response = requests.get(url) html_content = response.content.decode("utf-8") chapter_list_html = re.findall( r'<ul class="chapter-list clearfix">.*?</ul>', html_content, flags=re.DOTALL)[0] titles = re.findall( r'<a.*?title="(.*?)".*?>', chapter_list_html) for title in titles: print(title) print(f"共爬取到 {len(titles)} 条记录") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值