目录
- 前言
- 一、正则表达式核心语法(爬虫必备)
-
- 1.1 匹配单个字符:精准定位字符类型
- 1.2 匹配数量:控制字符重复次数
- 1.3 边界匹配:限定位置,避免匹配多余内容
- 1.4 分组与捕获:爬虫核心,提取想要的内容
- 1.5 贪婪与非贪婪匹配:爬虫最容易踩坑点
- 二、Python re 模块常用函数(爬虫高频必用)
-
- 2.1 re.match():从字符串开头匹配
- 2.2 re.search():搜索第一个匹配项
- 2.3 re.findall():返回所有匹配结果(爬虫最重要)
- 2.4 re.sub():替换清洗文本
- 2.5 re.compile():预编译正则,提高效率
- 2.6 正则修饰符(爬虫必备)
- 三、爬虫高频实战场景(4个通用模板,直接复制使用)
-
- 3.1 实战一:提取网页中所有URL链接
- 3.2 实战二:提取HTML标签内文本
- 3.3 实战三:提取中国大陆手机号
- 3.4 实战四:提取邮箱地址
- 四、综合实战:正则解析豆瓣电影TOP250(完整项目级案例)
-
- 4.1 实战目标
- 4.2 模拟豆瓣HTML源码
- 4.3 完整提取代码
- 4.4 贪婪 vs 非贪婪结果对比
- 五、正则表达式爬虫避坑指南(新手高频错误)
-
- 5.1 坑1:多行HTML忘记加 re.S
- 5.2 坑2:使用贪婪匹配导致内容错乱
- 5.3 坑3:特殊字符没有转义
- 5.4 坑4:findall 分组过多,返回元组
- 5.5 坑5:HTML标签嵌套导致匹配失败
- 5.6 坑6:空格、换行干扰匹配
- 六、正则表达式性能优化(高级爬虫技巧)
- 七、总结
前言
在网络爬虫开发、网页数据解析、文本清洗与信息提取的工作中,我们经常面对大量杂乱无章的 HTML 源码、接口返回文本、半结构化网页内容。网页里充斥着各种标签、空格、换行、特殊符号、注释、广告代码,如果直接肉眼筛选几乎不可能,而使用 XPath、BeautifulSoup 等解析库虽然方便,但在非标准 HTML、JS 动态片段、纯文本接口、不规则字符串场景下会束手无策。这时,**正则表达式(Regular Expression,简称 regex / re)**就成为爬虫工程师必不可少的核心工具。
正则表达式本质是一套字符串匹配规则语言,通过特殊符号组合,快速实现查找、匹配、捕获、替换、过滤、校验等操作。它的优势在于轻量、灵活、跨语言通用、不需要依赖第三方库,Python 内置的 re 模块开箱即用,是爬虫提取标题、链接、手机号、邮箱、价格、日期、ID、关键词的“万能武器”。
很多初学者觉得正则难学、符号多、容易写错,但只要掌握核心语法、数量匹配、分组捕获、贪婪与非贪婪、常用函数,就能应对爬虫中95%以上的文本提取场景。本文将系统讲解正则表达式完整语法、Python re 模块用法、四大爬虫高频实战案例、豆瓣电影真实项目解析、常见坑点与优化技巧,全文围绕爬虫实际工作场景展开,理论结合代码,帮助读者从零基础到熟练使用正则完成复杂网页信息提取。
一、正则表达式核心语法(爬虫必备)
正则语法分为五大模块:单个字符匹配、数量匹配、边界匹配、分组与捕获、贪婪与非贪婪,掌握这五部分,就能完成绝大多数爬虫提取需求。下面逐一详细讲解,并结合爬虫场景举例。
1.1 匹配单个字符:精准定位字符类型
单个字符匹配是正则的最小执行单元,用于规定“这个位置是什么类型字符”。爬虫中最常用的符号如下:
爬虫举例:
- 匹配手机号第二位:1[3-9]\\d{9},其中 [3-9] 限定第二位只能是3~9。
- 匹配链接:https?://[^\\s<>"]+,[^\\s<>"] 排除空格、标签、引号,精准截取完整URL。
1.2 匹配数量:控制字符重复次数
网页中的内容长度不固定,比如标题长短不一、评分可能1位或2位、年份固定4位,这就需要数量限定符控制前面字符出现多少次,这是爬虫最常用的语法。
爬虫实战理解: 如果要提取中国大陆手机号,规则是:1开头,第二位3-9,后面9位数字。 正则就是:1[3-9]\\d{9},其中 \\d{9} 严格匹配后面9位数字,保证11位手机号精准提取。
1.3 边界匹配:限定位置,避免匹配多余内容
边界符号用来规定匹配内容在字符串的什么位置,防止匹配到片段、部分内容,常用于校验格式、精准提取。
举例:
- ^http:只匹配以http开头的链接,不会匹配文本中间的http。
- \\b138\\d{8}\\b:精准匹配手机号,不会匹配到1138xxxx这类错误号码。
1.4 分组与捕获:爬虫核心,提取想要的内容
分组是正则最强大的功能,也是爬虫必须掌握的重点。正则可以匹配一大段内容,但我们往往只需要其中一部分,使用括号 () 就可以把需要的内容单独捕获出来。
爬虫最经典案例: 提取 <div class="name">流浪地球</div> 中的电影名,正则: r'<div class="name">(.*?)</div>' 运行后直接拿到括号内的“流浪地球”,而不是整个标签。
1.5 贪婪与非贪婪匹配:爬虫最容易踩坑点
这是90%爬虫新手写正则出错的根源。
- 贪婪匹配:.*,默认模式,尽可能匹配最长的内容,会一直匹配到最后一个结束符。
- 非贪婪匹配:.*?,尽可能匹配最短的内容,匹配到第一个结束符就停止。
举例对比: 文本:<div>电影A</div><div>电影B</div>
- 贪婪正则:<div>(.*)</div>,匹配结果是 电影A</div><div>电影B,直接把两个标签内容全部吞掉,完全错误。
- 非贪婪正则:<div>(.*?)</div>,匹配结果依次是 电影A、电影B,完全正确。
爬虫铁律:只要提取标签内文本,一律使用非贪婪匹配 .*?。
二、Python re 模块常用函数(爬虫高频必用)
Python 内置 re 模块,无需额外安装,提供5个核心函数,掌握这5个函数就能完成爬虫99%的正则操作。下面逐个讲解语法、参数、使用场景、示例代码。
2.1 re.match():从字符串开头匹配
re.match(pattern, string, flags=0) 特点:只从字符串最开头匹配,开头不符合直接返回None。 适用场景:格式校验,比如校验手机号、邮箱是否正确;不适合网页爬虫文本提取,因为网页内容不会以目标数据开头。
示例代码:
import re
text = "python爬虫学习"
res = re.match(r"python", text)
print(res.group())
2.2 re.search():搜索第一个匹配项
re.search(pattern, string, flags=0) 特点:扫描整个字符串,找到第一个匹配内容就返回,不管位置在哪。 适用场景:提取单个数据,如页面唯一标题、唯一评分。
示例:
text = "价格:99元,库存:100"
res = re.search(r"\\d+", text)
print(res.group()) # 输出99
2.3 re.findall():返回所有匹配结果(爬虫最重要)
re.findall(pattern, string, flags=0) 特点:查找字符串中所有匹配内容,以列表形式返回。 爬虫90%场景都用这个函数! 规则:
- 正则无括号分组:返回完整匹配内容;
- 正则有括号分组:只返回括号内的捕获内容。
示例:
text = "12a34b56c"
res = re.findall(r"\\d+", text)
print(res) # ['12','34','56']
2.4 re.sub():替换清洗文本
re.sub(pattern, repl, string, count=0, flags=0) 特点:把匹配到的内容替换成指定字符,爬虫常用于清理HTML标签、去除空格、过滤垃圾符号。
示例:去除所有HTML标签
html = "<h1>标题</h1><p>正文</p>"
clean_text = re.sub(r"<.*?>", "", html)
print(clean_text) # 标题正文
2.5 re.compile():预编译正则,提高效率
re.compile(pattern, flags=0) 特点:提前把正则表达式编译成对象,多次循环爬取、批量解析页面时,速度大幅提升。 适用场景:爬虫循环解析大量列表页、多页数据提取。
示例:
pattern = re.compile(r"\\d+")
res1 = pattern.findall("123abc456")
res2 = pattern.findall("789xyz000")
2.6 正则修饰符(爬虫必备)
爬虫最常用两个:
几乎所有网页正则提取,都要加上 re.S。
三、爬虫高频实战场景(4个通用模板,直接复制使用)
下面4个案例是爬虫行业通用模板,正则可以直接复制到自己项目里使用,覆盖链接提取、文本提取、手机号提取、邮箱提取。
3.1 实战一:提取网页中所有URL链接
需求:从杂乱HTML里提取全部http/https链接。 正则:r'https?://[^\\s<>"]+' 解析:
- https?:匹配http或https;
- ://:固定协议符号;
- [^\\s<>"]+:匹配非空格、非尖括号、非引号的连续字符,保证链接完整。
完整代码:
import re
html = '官网:https://www.douban.com 测试:http://demo.com 广告:https://ad.cn'
urls = re.findall(r'https?://[^\\s<>"]+', html)
print(urls)
3.2 实战二:提取HTML标签内文本
需求:提取h1标题、div标题、span标题。 通用模板:r'<标签名.*?>(.*?)</标签名>'
示例代码:
html = '<h1 class="title">Python爬虫实战教程</h1>'
title = re.findall(r'<h1.*?>(.*?)</h1>', html, re.S)
print(title[0])
3.3 实战三:提取中国大陆手机号
正则:r'1[3-9]\\d{9}' 代码:
text = "联系电话:13812345678 备用:19987654321"
phones = re.findall(r'1[3-9]\\d{9}', text)
print(phones)
3.4 实战四:提取邮箱地址
正则:r'\\w+@\\w+\\.\\w+' 代码:
text = "商务邮箱:contact@test.com 个人:user@qq.com"
emails = re.findall(r'\\w+@\\w+\\.\\w+', text)
print(emails)
四、综合实战:正则解析豆瓣电影TOP250(完整项目级案例)
4.1 实战目标
模拟爬虫真实场景,从豆瓣电影列表HTML中批量提取: 电影名称、评分、上映年份、地区、类型。 通过本案例掌握:非贪婪匹配、分组捕获、多行匹配、批量循环提取、贪婪与非贪婪对比。
4.2 模拟豆瓣HTML源码
<div class="item">
<div class="info">
<span class="title">肖申克的救赎</span>
<span class="rating_num">9.7</span>
<div class="bd">
<p class="">1994 / 美国 / 犯罪 剧情</p>
</div>
</div>
</div>
<div class="item">
<div class="info">
<span class="title">霸王别姬</span>
<span class="rating_num">9.6</span>
<div class="bd">
<p class="">1993 / 中国大陆 / 剧情 音乐</p>
</div>
</div>
</div>
4.3 完整提取代码
import re
html = '''
<div class="item">
<div class="info">
<span class="title">肖申克的救赎</span>
<span class="rating_num">9.7</span>
<div class="bd">
<p class="">1994 / 美国 / 犯罪 剧情</p>
</div>
</div>
</div>
<div class="item">
<div class="info">
<span class="title">霸王别姬</span>
<span class="rating_num">9.6</span>
<div class="bd">
<p class="">1993 / 中国大陆 / 剧情 音乐</p>
</div>
</div>
</div>
'''
# 第一步:提取每一个电影item块,必须非贪婪+re.S
item_pattern = re.compile(r'<div class="item">(.*?)</div>', re.S)
item_list = item_pattern.findall(html)
# 第二步:循环提取每部电影信息
for item in item_list:
# 电影名
name = re.findall(r'<span class="title">(.*?)</span>', item, re.S)
# 评分
score = re.findall(r'<span class="rating_num">(.*?)</span>', item, re.S)
# 年份
year = re.findall(r'(\\d{4})', item)
# 地区
area = re.findall(r'\\d{4} / (.*?) /', item, re.S)
if name and score and year:
print(f"电影:{name[0]}")
print(f"评分:{score[0]}")
print(f"年份:{year[0]}")
print(f"地区:{area[0]}")
print("-"*40)
4.4 贪婪 vs 非贪婪结果对比
五、正则表达式爬虫避坑指南(新手高频错误)
5.1 坑1:多行HTML忘记加 re.S
. 默认不匹配换行符,网页标签都是换行的,不加 re.S 直接匹配不到内容。 错误:re.findall(r'<div>(.*?)</div>', html) 正确:re.findall(r'<div>(.*?)</div>', html, re.S)
5.2 坑2:使用贪婪匹配导致内容错乱
只要提取标签内容,绝对禁止 .*,必须用 .*?。
5.3 坑3:特殊字符没有转义
正则中 . * + ? ( ) [ ] $ ^ 都是特殊符号,需要匹配本身时必须加 \\ 转义。 例如匹配评分 9.7,正则要写成 \\d+\\.\\d+,不能直接写 \\d+.\\d+。
5.4 坑4:findall 分组过多,返回元组
如果写了多个括号,findall 会返回元组列表。 例:re.findall(r'(\\d+)-(\\d+)', text),结果是 [(2024,01), (2025,02)]。
5.5 坑5:HTML标签嵌套导致匹配失败
比如 <div><span>文本</span></div>,直接匹配 <div>(.*?)</div> 会把span标签也抓进去。 解决办法:先用 re.sub 清理内部标签,再提取文本。
5.6 坑6:空格、换行干扰匹配
网页源码有大量空格换行,正则尽量使用 \\s* 匹配任意空白,提高容错。
六、正则表达式性能优化(高级爬虫技巧)
七、总结
正则表达式是爬虫文本提取的终极利器,尤其在非标准网页、动态片段、接口文本、不规则数据中,比XPath、BeautifulSoup更灵活、高效。本文系统讲解了正则全部核心语法:单个字符匹配、数量匹配、边界匹配、分组捕获、贪婪与非贪婪;讲解了Python re模块5个核心函数;给出4个爬虫通用实战模板;完成豆瓣电影真实案例;总结了新手高频坑点与优化技巧。
爬虫正则使用核心口诀: 点号任意、数字\\d、单词\\w、空白\\s; 数量+*?,非贪婪必加?; 分组()抓内容,多行必加re.S; findall抓全部,compile提效率。
掌握正则后,我们可以轻松完成:提取标题、链接、手机号、邮箱、价格、日期、关键词、批量列表数据、清洗HTML垃圾标签、过滤广告内容等工作,极大提升爬虫开发效率,是爬虫工程师必须掌握的基础核心技能。




