Python技术迷

Python爬虫常用正则表达式大全

哎,前两天晚上在公司加班,十一点多还在工位上,外卖都凉了我还没吃,头发掉了一地...就为了爬个破网站,正则真是把我折磨得想辞职。说到Python爬虫,大家不是都觉得 requests + BeautifulSoup 搞定一切嘛,但一碰到那种内容混在一起、标签乱七八糟的页面,老老实实用正则吧,不然你还真没招。

有一回,我们组那个小李,非要写个自动下载小姐姐图片的脚本(你懂的哈...),结果直接用BeautifulSoup,人家把图片链接藏在一坨js代码里,他当时直接懵逼了,跑来问我,"哥你正则怎么写才快啊?"我正吃泡面差点呛死,随手给他写了一个,反正那天也不急着下班。

正则基础用法

怎么说呢,其实最开始用re模块的时候,大家基本都这样:

import re

content = '手机号: 13612345678, 邮箱: [email protected]'
phone = re.findall(r'1\d{10}', content)
email = re.findall(r'\w+@\w+\.\w+', content)
print(phone, email)

就是,最简单的嘛,找手机号、找邮箱、还有那种身份证、QQ号,十个爬虫八个都用过。那个正则的\d就是数字,\w是字母和数字加下划线(word character),写多了闭着眼都能背下来。

有时候我写正则会加点花活,比如要抓URL或者那种带http、https的:

urls = re.findall(r'https?://[\w./]+', html)

这里那个s?的问号,意思就是可有可无,所以http和https都能匹配。小李那会儿老写错,把问号写成*,直接炸了,所有http都没了,给我笑死。

常用的正则表达式

现在我办公室电脑桌面就有个txt,存着这些常用的,省得每次百度,浪费时间:

  • 手机号:1\d{10}
  • 邮箱:\w+@\w+\.\w+
  • IP地址:(?:\d{1,3}\.){3}\d{1,3}
  • 身份证号:\d{17}[\dxX]
  • 金额:\d+(\.\d+)?
  • 时间(2025-07-07这种):\d{4}-\d{2}-\d{2}

比如有一次我要爬某个招聘网站的工资信息,页面写得特别花,"月薪:8k-15k/月",正则一上:

salary = re.findall(r'(\d+)k-(\d+)k', text)

完事儿,老板以为我多牛,其实就写了这么两行。

分组与命名分组

这个东西新手不太会用,其实分组是正则的大杀器。你像这种:

text = '姓名:张三,电话:13988889999'
match = re.search(r'姓名:(.*),电话:(\d+)', text)
if match:
    print(match.group(1))  # 张三
    print(match.group(2))  # 13988889999

你看,括号里面的就是一组一组的。还有那种命名分组,其实平时不用都忘了:

match = re.search(r'姓名:(?P<name>.*),电话:(?P<phone>\d+)', text)
if match:
    print(match.group('name'), match.group('phone'))

这种写法,你后面代码可读性就高,谁都能一眼看懂。

贪婪与非贪婪

说句真心话,这玩意儿坑了我不止一次,就是那个和?的区别。比如你要抓html里的某个标签内容:

html = '<div>内容一</div><div>内容二</div>'
result = re.findall(r'<div>(.*?)</div>', html)
print(result)

你不用问号它会把所有

和最后一个

之间的都抓下来,中间内容就全丢了。非贪婪,就是加个?,每次只匹配最近的那个。

替换和分割

前阵子我们要清理一批脏数据,就是一堆乱七八糟的字符,全塞数据库了,老板让写脚本一口气改干净。那用正则替换最方便:

text = 'a123b456c'
cleaned = re.sub(r'[a-z]', '', text)
print(cleaned)  # 123456

还有分割,比如抓那种一大堆数字拼一起的验证码:

text = '验证码:1,2,3,4'
codes = re.split(r'\D+', text)
print(codes)  # ['', '1', '2', '3', '4']

不过头和尾有空字符串,记得手动去掉。

re.compile提升效率

这个其实挺重要,写大爬虫项目的时候,你别每次都写死在re.findall,最好先compile一把,不然你开多线程跑,CPU给你顶满。

pattern = re.compile(r'\d{4}-\d{2}-\d{2}')
result = pattern.findall(text)

像我那次爬十万条数据,没compile直接爆内存,compile完好歹不卡了。

正则提取多行内容

有一次帮朋友抓B站弹幕,那个弹幕时间戳是多行文本里到处飞,要提取就要加re.S:

text = '''
<div>评论1</div>
<div>评论2
多行
</div>
'''

res = re.findall(r'<div>(.*?)</div>', text, re.S)
print(res)

要是不加re.S,那个点就匹配不了换行,啥都抓不到。

反向引用和断言

这种写法少用,但有些变态网站防爬你不用还真不行。比如提取成对的括号内容:

s = 'abc(123)def(456)'
print(re.findall(r'\((.*?)\)', s))

还有断言,用来只匹配特定前后缀的内容:

text = 'abc123def'
print(re.findall(r'(?<=abc)\d+(?=def)', text))  # ['123']

我现在的习惯,就是写爬虫的时候,正则表达式先搞一个大列表,常用的都存着,实在写不出来就去regex101网站丢进去试一下,别死磕。我也不跟你扯那些优雅写法,够用就行,反正网站一换页面结构,之前的正则也得重写,别太较真。

最后给大家一句忠告,正则是好用,但一用过多你自己后面都不认得自己写的代码,有空多写写注释,省得半年后回头骂自己哈。

-END-

我为大家打造了一份RPA教程,完全免费:https://www.songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领