欢迎光临
我们一直在努力

Python快速入门专业版(五十八)——正则表达式(re):爬虫文本提取利器(从语法到实战)

目录

  • 前言
  • 一、正则表达式核心语法(爬虫必备)
    • 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 匹配单个字符:精准定位字符类型

单个字符匹配是正则的最小执行单元,用于规定“这个位置是什么类型字符”。爬虫中最常用的符号如下:

  • . 点号:匹配任意单个字符,除换行符 \\n。常用于模糊匹配一段不确定的内容,比如网页标签之间的任意文本。
  • \\d:匹配任意一个数字,等价于 [0-9],专门用来提取手机号、年份、价格、ID、编号等数字类数据。
  • \\D:匹配任意非数字字符,用于过滤数字,只保留文字、符号。
  • \\w:匹配字母、数字、下划线,等价于 [a-zA-Z0-9_],常用于提取用户名、关键词、英文编码、链接后缀。
  • \\W:匹配非单词字符,如空格、@、#、&等特殊符号。
  • \\s:匹配空白字符,包括空格、制表符、换行、回车,爬虫中用于清理网页多余空格、换行。
  • \\S:匹配非空白字符,用于提取连续有效内容。
  • [] 字符集:[abc] 匹配 a、b、c 中任意一个;[0-9] 匹配数字;[a-z] 匹配小写字母;[3-9] 匹配手机号第二位。
  • [^] 取反字符集:[^<>"] 匹配不是尖括号、引号的字符,提取URL时常用,避免匹配到标签。
  • 爬虫举例:

    • 匹配手机号第二位:1[3-9]\\d{9},其中 [3-9] 限定第二位只能是3~9。
    • 匹配链接:https?://[^\\s<>"]+,[^\\s<>"] 排除空格、标签、引号,精准截取完整URL。

    1.2 匹配数量:控制字符重复次数

    网页中的内容长度不固定,比如标题长短不一、评分可能1位或2位、年份固定4位,这就需要数量限定符控制前面字符出现多少次,这是爬虫最常用的语法。

  • *:匹配前面字符 0次或多次,可以没有,也可以无限多。 例如 \\d*:匹配0个或多个数字,可用于提取不确定长度的编号。
  • +:匹配前面字符 1次或多次,至少出现1次,爬虫使用频率最高。 例如 \\w+:提取一段连续文本,至少1个字符。
  • ?:匹配前面字符 0次或1次,表示可有可无。 例如 https?:匹配 http 或 https,s可以有也可以没有。
  • {n}:固定匹配 n 次。 例如 \\d{4}:匹配4位数字,专门提取年份。
  • {n,m}:匹配 n~m 次。 例如 \\d{1,2}:匹配1~2位数字,提取电影评分 9、9.5。
  • {n,}:匹配至少n次。 例如 \\s{2,}:匹配两个以上空格,用于清洗网页多余空白。
  • 爬虫实战理解: 如果要提取中国大陆手机号,规则是:1开头,第二位3-9,后面9位数字。 正则就是:1[3-9]\\d{9},其中 \\d{9} 严格匹配后面9位数字,保证11位手机号精准提取。

    1.3 边界匹配:限定位置,避免匹配多余内容

    边界符号用来规定匹配内容在字符串的什么位置,防止匹配到片段、部分内容,常用于校验格式、精准提取。

  • ^:匹配字符串开头,多行模式下匹配每行开头。
  • $:匹配字符串结尾,多行模式下匹配每行结尾。
  • \\b:单词边界,匹配字母/数字与非字母数字的交界处,用于精准匹配独立单词。
  • \\B:非单词边界。
  • 举例:

    • ^http:只匹配以http开头的链接,不会匹配文本中间的http。
    • \\b138\\d{8}\\b:精准匹配手机号,不会匹配到1138xxxx这类错误号码。

    1.4 分组与捕获:爬虫核心,提取想要的内容

    分组是正则最强大的功能,也是爬虫必须掌握的重点。正则可以匹配一大段内容,但我们往往只需要其中一部分,使用括号 () 就可以把需要的内容单独捕获出来。

  • (xxx):普通捕获分组,括号内的内容会被单独提取。 例:<h1>(.*?)</h1>,括号内就是h1标签里的标题文本。
  • \\1:反向引用,匹配第一个分组捕获到的内容,常用于匹配成对标签、成对符号。
  • (?:xxx):非捕获分组,只用来匹配,不单独提取,优化正则性能。
  • 爬虫最经典案例: 提取 <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:使 . 点号可以匹配换行符,网页HTML都是多行,必须加。
  • re.I:忽略大小写。
  • 几乎所有网页正则提取,都要加上 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 非贪婪结果对比

  • 贪婪写法:<div class="item">(.*)</div> 直接把所有电影内容当成一个整体,无法拆分,提取失败。
  • 非贪婪写法:<div class="item">(.*?)</div> 逐个拆分每一部电影,精准提取,爬虫唯一正确写法。
  • 五、正则表达式爬虫避坑指南(新手高频错误)

    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* 匹配任意空白,提高容错。

    六、正则表达式性能优化(高级爬虫技巧)

  • 优先非贪婪匹配,减少正则回溯,提高速度。
  • 批量爬取必须使用 re.compile 预编译,速度提升30%以上。
  • 不用万能的 .*?,尽量用精准字符集,如 [^<] 代替 .*?。
  • 只保留需要的捕获分组,减少多余括号。
  • 长网页先切片,再用正则提取,减少匹配范围。
  • 七、总结

    正则表达式是爬虫文本提取的终极利器,尤其在非标准网页、动态片段、接口文本、不规则数据中,比XPath、BeautifulSoup更灵活、高效。本文系统讲解了正则全部核心语法:单个字符匹配、数量匹配、边界匹配、分组捕获、贪婪与非贪婪;讲解了Python re模块5个核心函数;给出4个爬虫通用实战模板;完成豆瓣电影真实案例;总结了新手高频坑点与优化技巧。

    爬虫正则使用核心口诀: 点号任意、数字\\d、单词\\w、空白\\s; 数量+*?,非贪婪必加?; 分组()抓内容,多行必加re.S; findall抓全部,compile提效率。

    掌握正则后,我们可以轻松完成:提取标题、链接、手机号、邮箱、价格、日期、关键词、批量列表数据、清洗HTML垃圾标签、过滤广告内容等工作,极大提升爬虫开发效率,是爬虫工程师必须掌握的基础核心技能。

    赞(0)
    未经允许不得转载:171主机测评 » Python快速入门专业版(五十八)——正则表达式(re):爬虫文本提取利器(从语法到实战)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址