Python正则案例如何匹配文本内容(实战手册)
📖 文章目录导读
- 正则表达式核心认知:为什么Python需要它?
- re模块基础匹配语法速查
- 6个真实Python正则案例深度解析
- 案例1:提取网页中的所有邮箱地址
- 案例2:验证手机号/身份证格式
- 案例3:从日志中抓取IP及时间戳
- 案例4:批量替换敏感词(如电话、银行卡)
- 案例5:分割并清洗CSV中不规则字段
- 案例6:匹配HTML标签并提取内部文本
- 常见匹配陷阱与性能优化
- SEO优化提示与问答互动
正则表达式核心认知:为什么Python需要它?
在日常的文本处理、数据清洗、爬虫提取甚至自动化运维任务中,正则表达式(Regular Expression)几乎是每个Python开发者必须掌握的武器,它能用极少的代码,完成对海量文本的模式识别、提取、替换等操作。

当你想从1000封邮件中提取出所有订单号,或者从乱糟糟的日志中过滤出错误码,Python的re模块就是你的专属“文本手术刀”。
通俗定义:正则是一种描述“字符串模式”的公式语言,例如\d{3,4}-\d{7,8}就能匹配座机号码(010-12345678),而[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}几乎能匹配所有标准邮箱。
re模块基础匹配语法速查
在深入案例前,先回顾Python re模块最常用的三个函数:
| 函数 | 作用 | 示例 |
|---|---|---|
re.findall(pattern, text) |
返回所有匹配的列表 | re.findall(r'\d+', 'abc123def456') → ['123','456'] |
re.search(pattern, text) |
扫描全文,返回第一个匹配对象(Match对象) | 可用.group()取值 |
re.sub(pattern, repl, text) |
替换匹配到的文本 | re.sub(r'\s+', ' ', text) 合并多余空格 |
注意:Python的
pattern强烈建议使用原始字符串(r''),避免反斜杠被转义。
6个真实Python正则案例深度解析
案例1:提取网页中的所有邮箱地址
场景:你爬取了一个商家的“联系我们”页面,需要提取所有联系邮箱。
代码:
import re
html = '请联系:support@example.com 或 sales@tech.com.cn,勿发垃圾邮件。'
emails = re.findall(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b', html)
print(emails) # ['support@example.com', 'sales@tech.com.cn']
解析:这里的\b表示单词边界,防止匹配到类似email@前面还有字符的情况。{2,7}表示域名后缀长度(如.com、.org、.tech)。
案例2:验证手机号/身份证格式
场景:用户注册时,需要校验输入的手机号是否符合中国大陆规则(11位,以1开头,第二位通常为3/5/7/8/9)。
代码:
def is_valid_phone(phone):
pattern = r'^1[3-9]\d{9}$'
if re.match(pattern, phone):
return True
return False
print(is_valid_phone('13800138000')) # True
print(is_valid_phone('12345678901')) # False
身份证18位校验:若需同时校验位数和生日逻辑,可用^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$。
案例3:从日志中抓取IP及时间戳
场景:Nginx访问日志格式:168.1.1 - - [10/Oct/2023:13:55:36 +0800] "GET /index " 200 2326,需要提取IP和时间。
代码:
log_line = '192.168.1.1 - - [10/Oct/2023:13:55:36 +0800] "GET /index" 200 2326'
pattern = r'(\d+\.\d+\.\d+\.\d+).*?\[(\d{2}/\w{3}/\d{4}:\d{2}:\d{2}:\d{2})'
match = re.search(pattern, log_line)
if match:
ip, timestamp = match.groups()
print(ip, timestamp)
# 输出:192.168.1.1 10/Oct/2023:13:55:36
技巧:是非贪婪匹配,避免跨越太多字符,内需转义真实中括号。
案例4:批量替换敏感词(如电话、银行卡)
场景:为了保护用户隐私,需要将文本中连续8位及以上数字(可能是手机号或卡号)替换为。
代码:
text = '我的卡号是 6222021234567890,电话13800138000。'
clean = re.sub(r'\d{8,}', '****', text)
print(clean) # 我的卡号是 ****,电话****。
进阶:若需要保留特定格式(如银行卡前4位),可用\1引用分组替换。
案例5:分割并清洗CSV中不规则字段
场景:CSV文件中某字段包含逗号或引号,如:"张三, 工程师", 28, "备注:, 好",常规.split(',')会出错。
代码:
csv_line = '"张三, 工程师", 28, "备注:, 好"'
# 匹配所有被双引号包裹的字段或普通非逗号字段
fields = re.findall(r'"[^"]*"|[^,]+', csv_line)
# 去掉每个字段的多余引号
cleaned = [f.strip().strip('"') for f in fields]
print(cleaned) # ['张三, 工程师', '28', '备注:, 好']
原理:优先匹配引号内所有字符(含逗号),匹配无引号的简单字段。
案例6:匹配HTML标签并提取内部文本
场景:从简单富文本中提取<p>标签内的内容,同时剔除所有标签。
代码:
html = '<div><p>这是重点内容</p><a href="...">忽略链接</a></div>' # 方法1:提取特定标签内部文本 p_contents = re.findall(r'<p>(.*?)</p>', html, re.DOTALL) print(p_contents) # ['这是重点内容'] # 方法2:删除所有标签,只留纯文本 pure_text = re.sub(r'<[^>]+>', '', html) print(pure_text) # 这是重点内容忽略链接
注意:不推荐正则处理复杂HTML(如嵌套标签),请用BeautifulSoup,但简单提取完全够用。
常见匹配陷阱与性能优化
-
贪婪 vs 非贪婪:默认、是贪婪匹配(尽可能多),需用、改为非贪婪。
<div>(.*?)</div>只会匹配最近的一个闭合标签。 -
换行符处理:若文本跨多行,记得在
re.findall中加入re.DOTALL标志,让能匹配换行符。 -
性能建议:如果你要对同一模式大量匹配(如100万条日志),先编译正则:
pattern = re.compile(r'\d{3}-\d{8}') results = pattern.findall(10000行文本)编译后可重复使用,速度快5~10倍。
-
反向引用:用
\1引用分组,例如匹配重复单词:r'(\b\w+)\s+\1'可匹配“hello hello”。
SEO优化提示与问答互动
SEO提示:本文围绕“Python正则案例”“文本内容匹配”“正则表达式实战”等长尾关键词展开,文中每个案例都提供了可直接运行的代码块,且使用了标题层级(H1/H2/H3),结构化内容有利于搜索引擎理解,案例覆盖了爬虫、日志分析、数据清洗高频场景,能吸引不同需求的读者。
❓ 常见问答
Q1:为什么我用re.match总是匹配失败?
A:re.match默认从字符串开头匹配,如果模式不是在开头,请改用re.search。
Q2:我想匹配中文文本,应该怎么写?
A:使用Unicode属性:r'[\u4e00-\u9fff]+'可以匹配连续中文字符。re.findall(r'[\u4e00-\u9fff]+', '你好world') → ['你好']。
Q3:如何匹配包含换行的大段文字?
A:在re.findall第三个参数传入re.DOTALL,让匹配任意字符(包括换行),如匹配"""AAA\nBBB"""中的AAA换行BBB:r'A.*?B'配合re.DOTALL。
Q4:有没有不需要记忆正则的备选方案?
A:对于结构固定、简单的文本,可以用Python字符串方法(str.find、split)或内置string模块,但一旦牵涉复杂模式(如邮箱、嵌套括号),正则依然是无可替代的。
Python正则匹配文本内容的能力,在于“用模式描述规律”,通过以上6个实战案例,你已经了解了从邮箱提取、格式校验到日志清洗的常见写法,建议你在实际项目中,先从简单模式写起,逐步叠加规则(如开头、(?i)忽略大小写),并善用re.VERBOSE给正则加注释,提升可维护性。
打开你的Python环境,尝试用正则解决一个你手头最棘手的文本问题吧。