Python爬虫正则表达式详解:re模块方法与爬虫应用实战指南

本篇文章主要给大家分享爬虫里的正则表达式。在 Python 基础阶段,就会简单地涉及到正则表达式。但在那个时候,不会将其与爬虫内容结合起来进行讲解。

Python爬虫正则表达式详解:re模块方法与爬虫应用实战指南

本篇主要介绍内容如下:

正则表达式与re模块

re模块方法介绍

re模块在爬虫中的应用

正则表达式与re模块

什么是正则表达式?

正则表达式又称规则表达式,通常用于检索和替换符合特定模式的文本。它首先设定了一些特殊的字符及字符组合,然后通过组合这些“规则字符串”来对字符串进行过滤,以获取或匹配我们想要的特定内容。

它使用起来较为灵活,逻辑性较强且功能性也较强,能够迅速借助表达式从字符串里找到所需信息,不过对于初次接触的人而言,是比较晦涩且难以理解的。

正则表达式并非仅存在于 Python 中,其他语言也具备正则表达式。像 Java、JavaScript 等语言就有。倘若你具备其他语言的正则表达式基础,那么学习本节内容就会轻松许多。

正则表达式进行检索的步骤:

re模块

Python 借助 re 模块来提供对正则表达式的支持。在使用正则表达式之前,需要将该库进行导入。

import re

在我们正式介绍re模块的方法之前,先了解一下匹配规则:

规则较多是吗?不过只要记住篮框标注的那些就可以啦,因为这些是最常用的。大家多使用几次,就会渐渐变得熟练起来。

特别提示:在使用正则表达式时,要对特殊字符进行转义。因此,如果我们想要使用原始字符串,就需要在字符串前面加上一个 r 前缀。

re模块方法介绍

re模块的常用方法

使用 re 模块中的 compile()函数,将正则表达式以字符串形式进行编译,从而得到一个 Pattern 对象。

使用 Pattern 所提供的一系列方法,能够对文本进行匹配查找操作,最终会获得一个 Match 对象。

最后使用Match对象提供的属性和方法获得信息

首先认识一下compile 函数,它的一般使用形式如下:

import re
# 将正则表达式编译成 Pattern 对象
pattern = re.compile(r'\w{3}')
print(pattern)

Pattern 对象的一些常用方法主要有:

match方法:

match 方法从字符串的 pos 下标处开始进行匹配 pattern 。如果在 pattern 结束时已经完成匹配,就会返回一个 Match 对象。

如果在匹配过程中,pattern 不能够进行匹配,又或者在匹配还没有结束的时候就已经到达了 endpos,那么就会返回 None。此方法的原型如下:

match 函数可以使用 string 作为参数,也可以指定 pos 和 endpos 来确定匹配的范围;re.match 函数则需要 pattern 作为匹配模式,同时可以使用 string 作为待匹配的字符串,还可以通过 flags 来设置一些匹配的标志。

参数 string 指的是字符串;pos 代表着下标,pos 的默认值是 0,endpos 的默认值是 len(string);参数 flags 是在编译 pattern 时用来指定匹配模式的。

其三,re.S(re.DOTALL),表示支持点任意匹配模式。

import re
# 1. 得到pattern
pattern = re.compile('abc')
使用公式对象来匹配需要校验的字符串,进行 match 匹配操作,然后会返回一个匹配对象 match 对象。
match_obj = pattern.match('abcdef')
print(match_obj)

运行结果:

# 表示有匹配对象

import re
# 1. 得到pattern
pattern = re.compile('abc')
# 2. 使用公式对象匹配要校验的字符串  match 匹配,返回一个匹配对象match对象
match_obj = pattern.match('helloabc')
print(match_obj)

运行结果是:None

此时 helloabc 中实际上是有 abc 这个内容的,然而为何 Match 对象却是 None 呢?这是因为 Match 在进行匹配判断时,都是从字符串的开头开始进行判断的。如果一开始没有匹配成功,就会返回 None 。但是倘若代码改成下面这样的形式,就会返回一个 Match 对象。

import re
# 1. 得到pattern
pattern = re.compile('abc')
# 2. 使用公式对象匹配要校验的字符串  match 匹配,返回一个匹配对象match对象
match_obj = pattern.match('helloabc',5)
# 3. 打印对象
print(match_obj)

上面是为了方便大家理解正则的检索过程。然而,在实际使用中,我们能够直接通过 re.match(pattern,字符串)来进行检索。

比如(各位觉得结果会是什么呢?)

import re
r = re.match('abc', 'helabclo')
print(r)

结果为 None ,原因是依旧从开头开始进行比较。然而实际上,我们要检索的内容很有可能处于字符串的中间或者后面,并非每次都在前面。在这种情况下,我们就需要使用 search 方法了。

search 方法:

使用 search 意味着从任意位置开始进行查找,且仅进行一次匹配。需要注意的是,一旦找到匹配项,就不会继续查找后面可能存在的其他匹配项了。

它的一般使用形式如下:

搜索字符串(可以指定起始位置[pos]和结束位置[endpos])

其中,待匹配的字符串是 string ,pos 和 endpos 为可选参数,用于指定字符串的起始位置和终点位置,其默认值分别是 0 和字符串的长度 len 。

匹配成功时,就会返回一个 Match 对象;若没有匹配上,就会返回 None。

import re
r = re.search('abc', 'helabcloabc')
print(r)

此时返回的结果:

Match对象有几个常用的方法:

group()的作用是获取一个或多个分组匹配的字符串。如果想要获取整个匹配的子串,既可以直接使用 group(),也可以使用 group(0)。

span(): 返回匹配字符串的起始位置

start():用于获取分组匹配的子串在整个字符串中的起始位置,也就是子串第一个字符的索引。参数的默认值为 0。

end():用于获取分组匹配的子串在整个字符串中的结束位置。这个结束位置指的是子串最后一个字符的索引加 1。参数默认值为 0。

import re
r = re.search('abc', 'helabcloabc')
if r:
    print(r.group())
    print(r.span())
    print(r.start())
    print(r.end())

结果是:

abc

(3, 6)

如果我们的正则定义变得复杂一些,并且使用上面的匹配规则,那么使用方式也是这样吗?

import re
match = re.search(r'([a-z]+) ([a-z]+)', )  # 注意此时是区分大小写的
if  match: 
 print(match.group(0))
 print(match.group(1)) # 获取第一个分组的字符串
 print(match.group(2)) # 获取第二个分组的字符串
 print(match.groups()) 

结果是:

itty hellobaby

itty

hellobaby

('itty', 'hellobaby')

上面的正则表达式表明有两组由多个 a-z 之间的任意字符构成的字符串,且两组间有空格。match.groups()所表达的意思为(m.group(1), m.group(2), …),由于上述代码仅为两组,所以只能获取到 match.group(2),但若获取 match.group(3)则会出现报错。

可是问题再次出现,当 search 找到符合要求的字符串后就不会继续进行查找了,然而实际上后面依然存在符合正则的情况。

比如:hello world

如果想要获取所有的内容,那么可以考虑使用 findall()。通过对英语进行分析,人们能够知道它的意思。

findall方法

findall 方法的使用形式如下:

查找字符串中的所有匹配项,可指定起始位置和结束位置。可以通过指定起始位置和结束位置来限制查找范围。在指定的字符串中查找所有符合条件的内容。可以根据需要设置起始位置和结束位置来进行特定范围的查找。在给定的字符串中找出所有满足条件的部分。能够在指定的字符串范围内查找所有匹配的内容。

其中,待匹配的字符串是 string ,pos 和 endpos 是可选参数,用于指定字符串的起始和终点位置,其默认值分别为 0 和字符串的长度 len 。findall 会以列表形式返回全部能匹配的子串,若没有匹配,则返回一个空列表。例如,通过上面的代码使用 findall() 来查看获取的结果是什么?

import re
match_list = re.findall(r'([a-z]+) ([a-z]+)', 'hello Kitty hellobaby hello world')  # 注意此时是区分大小写的
if match_list: 
 print(match_list)

结果:

["itty", "hellobaby"] 且 ["hello", "world"]

我们需要写一个正则表达式,这个正则表达式要能够检索出所有这样的字符串:字符串的开头和结尾是字母,而中间全部是数字。

import re
s = 'h88ex890loK123Jldkl90gd3o'

m = re.findall('[a-z][0-9]*[a-z]', s, re.I)

print(m)

结果:

如果要判断一个字符串是否以数字开头呢?我们可以使用 match 吗?可以使用 search 吗?可以使用 findall 吗?

import re
因为要注意是数字开头,所以我们主要进行开头的判断,因此我们使用 match 。
match = re.match(r'\d+.*','123admin')  #\(d\)在匹配规则方面表示数字,“+”表示次数为大于等于 1,“.”表示任意字符,“*”表示长度是大于等于 0。
if match:
  print('是数字开头的')
else:
    print('不是数字开头的')

结果打印:是数字开头的,字符串换成:admin呢?

下面代码的结果会是什么呢?

验证用户名需包含字母、数字和下划线。其首字母不能是数字,并且长度必须在 6 位以上。
username = 'admin123'
m = re.match('[a-zA-Z_]\w{5,}$', username)
print(m.group())

finditer 方法

finditer 方法的行为与 findall 类似,它会搜索整个字符串并获取所有匹配的结果。不过,它返回的是一个迭代器,能够顺序访问每一个匹配结果(Match 对象)。大家可以把上面的代码修改为 finditer 来观察结果,这里就不再展示代码了。

split 方法

split 方法会依据能够匹配的子串来对字符串进行分割,分割之后会返回一个列表。它的使用形式具体如下:

split(string[, maxsplit])

其中,maxsplit 被用来指定最大的分割次数。如果不指定,就会将其全部进行分割。它与字符串的分隔情况类似,然而,它在此方面更加灵活。

比如:

import re
s = "hello Kitty 是一个广为人知的形象。hello baby 也是一个常用的表达。hello world 是编程中常用的入门语句。hello8hello 则是包含数字 8 的一种组合。"

m = re.split(r'[\s\d]+', s) 遇到空白字符\s或者数字\d时都会进行切割,多个空格也能被切割,并非仅仅一个空格或数字能被切割。

print(m)

此时得到的结果是:

["hello","Kitty","hellobaby","hello","world","hello","hello"] 包含多个 "hello" 相关的元素,其中有 "Kitty" 以及 "hellobaby" 等。

sub方法

sub 方法用于替换。它的使用形式如下:

sub(repl, string[, count])

repl 可以是字符串也可以是一个函数:

如果 repl 为字符串,就会用 repl 来替换字符串中每一个匹配的子串,然后返回替换后的字符串。此外,repl 能够以 id 的形式来引用分组,不过不能使用编号 0 。

如果 repl 为函数,此方法应仅接受一个参数,该参数为 Match 对象,并且要返回一个用于替换的字符串,返回的字符串中不能再引用分组。

count 用于指定最多替换次数,不指定时全部替换

import re

# 比如替换敏感词汇
s = '小明喜欢苍老师'
m = re.sub(r'(苍井空|苍老师)', '***', s)  # 括号里面的表示一组,可以是这一组中的任何一个。
print(m)

# 将里面的分数都替换成100分
msg = 'python=99,c=98,html=90'
m = re.sub(r'\d+', '100', msg)
print(m)

当然也可以使用函数,比如分数都加1分

import re

def add(temp):
    print(temp) # 此处打印便于查看
    score = temp.group()  # 获取匹配的内容
    score = int(score) + 1
    return str(score)

m = re.sub(r'\d+', add, msg)
print(m)

在使用过程中会涉及分组、贪婪和非贪婪模式,这里暂不展开,若有时间会给大家专门写一篇文章。

re模块在爬虫中的应用

接下来给大家分享一些常用的关于正则表达式抓取网络数据的技巧。

抓取标签间的内容

我们之前的几篇文章向大家分享了 urllib 模块和 requests 模块,这两个模块是用于获取网络资源的。我们获取的网络资源,除了 json 之外,都是与 HTML 标签相关的。我们通常需要做的就是获取这些标签的内容。

比如我们获取一下百度的title标题:

import re  
import requests  
url = "http://www.baidu.com/"  
response = requests.get(url)
response.encoding='utf-8'
content = response.text
# 此处使用findall结合正则表达式完成
title = re.findall(r'(.*?)', content)
print(title[0])

抓取超链接标签间的内容

import re  
import requests  
url = "http://www.baidu.com/"  
response = requests.get(url)
response.encoding='utf-8'
content = response.text
# 定义正则表达式获取所有网页的超链接
res = r""
在 content 中,通过 re.findall 方法找到了 urls,这些 urls 符合 res 的匹配规则。
for u in urls:
    print(u)

当然,若要获取超链接中的内容,我们是可以使用正则表达式的。只是,使用了分组的内容为()。

import re  
import requests  
url = "http://www.baidu.com/"  
response = requests.get(url)
response.encoding='utf-8'
content = response.text

 
#获取超链接和之间内容
res = r'(.*?)'  
使用 re.findall 函数在 content 中按照 re.S|re.M 的模式查找 res ,查找的结果存储在 texts 中
for t in texts:
    print(t)

观察结果:

抓取标签中的参数

HTML 超链接有其基本格式为“链接内容”。现在要获取其中的 URL 链接地址,获取的方法如下。

import re  
import requests  
url = "http://www.baidu.com/"  
response = requests.get(url)
response.encoding='utf-8'
content = response.text
# 定义正则表达式获取所有网页的超链接
res = r""
urls = re.findall(res, content)
# 将所有的超级链接拼接成字符串
all_urls = '\n'.join(urls)
# 定义正则表达式
res = r"(?<=href=)http:.+?(?=\>)|(?<=href=)http:.+?(?=\s)"
# 查找符合规则的超级链接
通过使用 re.findall 函数,在 content 中按照 re.I|re.S|re.M 的模式去查找 res,从而得到 urls 。
for url in urls:
    print(url) 

抓取图片超链接标签的URL

HTML 插入图片使用标签的基本格式是“”。要插入图片,需要获取图片的 URL 链接地址。下面的案例不仅获取了图片链接,还将图片保存到了本地。

import re
import requests

# 从网络获取一张图片的html标签
image = ''
# 使用正则表达式获取src后面的内容
m = re.match(r', image)
print(m.group(1))
image_path = m.group(1)

如果想要下载获取的图片链接,我们可以将 requests 与文件保存结合起来完成。
通过 requests 获取了 image_path 对应的内容并赋值给 response 。
# 获取响应信息的内容
result = response.content
# 获取图片名称
filename 等于 image_path 在 image_path 中从后往前找到最后一个斜杠(包括斜杠)之后的部分。'%')+1:]
path = os.path.join(r'images', filename)
# 保存到本地将图片
with open(path, 'wb') as wstream:
    wstream.write(result)
print('文件下载结束!')

系列文章

你可能想看:
« 上一篇
下一篇 »

相关推荐

python爬虫教程PDF,Python爬虫书PDF

2026年09月02日

30阅读

外国教程python,python编程教学视频

2026年09月02日

24阅读

python简明教程沈洁元,python详细基础教程

2026年09月02日

21阅读

python库包教程,python 包

2026年09月02日

26阅读

python教程大全集,python教程600集

2026年09月02日

26阅读

python入门教程完整版,python零基础入门全套教程视频

2026年09月02日

22阅读