上一章的requests库是一个常用的 HTTP 请求库,可以方便地向网站发送 HTTP 请求,并获取响应结果。爬虫就是解析网页的内容将需要的信息爬取出来,本章节学习正则表达式的内容,正则表达式可以精准将需要的内容从整体中提取出来
目标:掌握正则表达式,让混乱的文本秒变“结构化数据”,从此告别“肉眼找规律”的苦逼生活!
学习目标:学会用正则匹配手机号、邮箱、身份证号,甚至“从一堆乱码中精准提取小姐姐的微信号”(开玩笑的,请遵纪守法)。
3.1 为什么学正则表达式?
(温馨提示:如果你觉得写字符串处理代码像“便秘”,学完本章你会“畅快淋漓”)
正则表达式的三大优势:
- 万能文本捕手:从杂乱无章的文本中提取关键信息(比如从一篇3000字的文章里揪出所有日期)
- 一行代码顶百行:用正则替换循环+判断(比如批量删除文件名中的空格)
- 江湖必备技能:面试常考、爬虫必备、数据处理神器
代码对比:普通方法 vs 正则
python
# 普通方法(假设要从字符串中提取所有数字)
text = "我的电话是123456,另一个是789012"
numbers = []
for i in range(len(text)):
if text[i].isdigit():
num = ""
while i < len(text) and text[i].isdigit():
num += text[i]
i += 1
numbers.append(num)
print(numbers) # ['123456', '789012'](写得我手都酸了)
# 正则方法(一行搞定):
import re
numbers = re.findall(r"\d+", text)
print(numbers) # ['123456', '789012'](正则:这都不是事儿)
3.2 正则基础语法:从“小白”到“入门”
元字符速记表(附搞笑注释)
符号 | 作用 | 举个栗子(匹配手机号) |
---|---|---|
. | 匹配任意字符(除了换行符) | 1.5 可以匹配 1a5 、135 等 |
\d | 匹配数字(等价于[0-9]) | \d{11} → 匹配11位数字(手机号) |
\w | 匹配字母/数字/下划线 | \w+ → 匹配类似user_123 的用户名 |
* | 前一个字符出现0次或多次 | ab*c → 匹配ac 、abc 、abbbc |
+ | 前一个字符出现1次或多次 | ab+c → 匹配abc 、abbbc ,但不匹配ac |
? | 前一个字符出现0次或1次 | colou?r → 匹配color 或colour |
{n,m} | 前一个字符出现n到m次 | \d{3,4} → 匹配3到4位数字(区号) |
` | ` | 或关系(二选一) |
^ | 匹配字符串开头 | ^Hello → 匹配以Hello 开头的字符串 |
$ | 匹配字符串结尾 | \d+$ → 匹配以数字结尾的字符串 |
代码示例:手机号匹配
python
import re
text = "联系我:手机13812345678,座机010-12345678"
pattern = r"1[3-9]\d{9}" # 手机号正则(国内11位)
# findall返回所有匹配结果
phones = re.findall(pattern, text)
print(phones) # ['13812345678']
# match从字符串开头匹配(如果手机号不在开头会匹配失败)
result = re.match(pattern, text)
print(result) # None(因为前面有“联系我:手机”)
3.3 常用函数:正则的“三板斧”
1. re.findall()
:暴力搜索所有匹配项
python
# 提取所有邮箱地址
text = "我的邮箱是a@b.com,备用邮箱c.d@e.co.uk"
emails = re.findall(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", text)
print(emails) # ['a@b.com', 'c.d@e.co.uk']
2. re.search()
:找到第一个匹配项
python
# 提取第一个日期
text = "会议时间:2023-10-01,截止日期:2023-12-31"
date_pattern = r"\d{4}-\d{2}-\d{2}"
first_date = re.search(date_pattern, text).group()
print(first_date) # '2023-10-01'
3. re.sub()
:文本替换神器
python
# 把所有空格替换成下划线(即使中间有多个空格)
text = "Hello World Python"
new_text = re.sub(r"\s+", "_", text)
print(new_text) # "Hello_World_Python"
4. re.split()
:按规则分割字符串
python
# 按非数字字符分割字符串
text = "abc123def456ghi"
parts = re.split(r"\D+", text) # \D+ 匹配一个或多个非数字
print(parts) # ['abc', '123', 'def', '456', 'ghi']
3.4 分组捕获:正则的“抓重点”技能
分组语法:用小括号()
标记分组
python
# 提取日期中的年月日
text = "日期:2023-10-01"
pattern = r"(\d{4})-(\d{2})-(\d{2})"
match = re.search(pattern, text)
if match:
year, month, day = match.groups()
print(f"年:{year}, 月:{month}, 日:{day}") # 年:2023, 月:10, 日:01
命名分组:给分组起个名字(方便后期调用)
python
pattern = r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})"
match = re.search(pattern, text)
if match:
print(match.group("year")) # 2023
3.5 贪婪与非贪婪模式:正则的“选择困难症”
贪婪模式(默认):尽可能多匹配
python
text = "<div>内容1</div><div>内容2</div>"
pattern = r"<div>(.*)</div>"
result = re.search(pattern, text)
print(result.group(1)) # "内容1</div><div>内容2"(匹配到最后一个</div>)
非贪婪模式:尽可能少匹配(加?
)
python
pattern = r"<div>(.*?)</div>"
result = re.findall(pattern, text)
print(result) # ['内容1', '内容2'](精准匹配每个div内容)
3.6 高级技巧:正则的“超能力”
1. 零宽断言:匹配位置而非内容
python
# 匹配后面跟着“元”的数字(比如价格后面的金额)
text = "价格:99元,原价:199元"
pattern = r"\d+(?=元)" # (?=元) 表示后面必须是“元”
print(re.findall(pattern, text)) # ['99', '199']
2. 编译正则表达式:提升效率
python
import re
pattern = re.compile(r"\d+") # 预编译正则表达式
numbers = pattern.findall("a1b22c333")
print(numbers) # ['1', '22', '333']
3. 处理复杂文本:邮箱去重
python
text = "联系我:a@a.com, b@b.com, a@a.com"
emails = list(set(re.findall(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", text)))
print(emails) # ['b@b.com', 'a@a.com']
3.7 错误处理:正则的“防崩溃”指南
python
try:
re.compile("]invalid[regex") # 故意写一个错误正则
except re.error as e:
print(f"正则语法错误:{e}") # 正则语法错误:nothing to repeat at position 0
3.8 学习渠道推荐:成为正则大师的捷径
-
在线练习:
- Regex101(实时调试+中文解释)
- 菜鸟教程正则表达式(中文入门宝典)
-
书籍推荐:
- 《精通正则表达式》(俗称“圣经”,看完能装逼)
- 《Python正则表达式操作指南》(实战派首选)
-
避坑指南:
- 避免过度使用贪婪模式(否则会匹配到奇怪的内容)
- 用
re.VERBOSE
写多行正则(加注释更清晰)python
pattern = re.compile(r""" \d{4} # 年份4位数字 - # 分隔符 \d{2} # 月份2位数字 - # 分隔符 \d{2} # 日期2位数字 """, re.VERBOSE)
3.9 本章小结
-
核心技能:
- 掌握元字符、分组、贪婪模式等基础语法
- 熟练使用
findall
、search
、sub
等函数 - 能用正则解决实际问题(如数据清洗、日志分析)
-
避坑指南:
- 正则写完后先用简单文本测试(避免线上翻车)
- 复杂正则建议拆解成多步骤处理(比如先提取再处理)
正则表达式的搞笑彩蛋:
如果正则表达式会说话,可能会吐槽:“人类总让我干脏活累活,却不知道我内心在咆哮:‘这字符串是外星文明写的吗?!’”