Python爬虫常用正则表达式大全
哎,前两天晚上在公司加班,十一点多还在工位上,外卖都凉了我还没吃,头发掉了一地...就为了爬个破网站,正则真是把我折磨得想辞职。说到Python爬虫,大家不是都觉得 requests + BeautifulSoup 搞定一切嘛,但一碰到那种内容混在一起、标签乱七八糟的页面,老老实实用正则吧,不然你还真没招。
有一回,我们组那个小李,非要写个自动下载小姐姐图片的脚本(你懂的哈...),结果直接用BeautifulSoup,人家把图片链接藏在一坨js代码里,他当时直接懵逼了,跑来问我,"哥你正则怎么写才快啊?"我正吃泡面差点呛死,随手给他写了一个,反正那天也不急着下班。
正则基础用法
怎么说呢,其实最开始用re模块的时候,大家基本都这样:
import recontent = '手机号: 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 全部免费领