目录
- 一、网络爬虫中的正则表达式和re模块
- (一)数据提取的精确性
- (二)处理复杂的文本结构
- (三)提高数据处理效率
- 二、正则表达式的内涵
- (一)、常用元字符
- (二)、量词(控制前面的元字符出现的次数)
- (三)、贪婪匹配和惰性匹配
- (四)、Python网络爬虫中的常用正则表达式
- (五)、Python中的re模块
- 三、典型案例
- (一). **提取网页中的所有链接**
- (二). **验证用户输入的电子邮件地址是否合法**
- (三). **从文本中提取电话号码**
在 Python 中,re模块提供了对正则表达式操作的支持,包括 匹配、搜索、替换、分割等功能,使得在网络爬虫中方便地运用正则表达式来处理抓取到的数据。
一、网络爬虫中的正则表达式和re模块
(一)数据提取的精确性
- 定位特定数据
- 在网页的HTML或其他文本数据中,目标数据往往混杂在大量无关信息中。例如,在一个电影网站上,要提取某部电影的评分,评分数据可能被包裹在特定的HTML标签内。
- 正则表达式可以精确地定位这些数据。比如,使用
<span class="rating_num">(.*?)</span>
这个正则表达式,可以在HTML中找到电影评分所在的<span>
标签,并提取其中的评分数值。
- 过滤无关信息
- 网络爬虫抓取的网页内容包含大量不需要的信息,如导航栏、广告、版权声明等。正则表达式可以帮助过滤掉这些无关数据。
- 例如,要从一个包含大量新闻文章的网页中提取正文内容,通过分析网页结构,发现正文内容在
<div class="article - content">
标签内,可以使用正则表达式<div class="article - content">(.*?)</div>
来提取正文,过滤掉其他非正文的HTML元素。
(二)处理复杂的文本结构
- 应对多样化的网页结构
- 不同网站的网页结构各异,甚至同一网站的不同页面可能也有不同的结构。正则表达式具有很强的灵活性,能够适应这种多样性。
- 例如,在一个电商网站上,商品价格可能在不同页面以不同的HTML格式呈现。有的可能是
<span id="price">19.99</span>
,有的可能是<div class="product - price">19.99</div>
。通过编写灵活的正则表达式,如<(span|div).*?(id="price"|class="product - price")>(.*?)</(span|div)>
,可以适应这种结构变化来提取价格信息。
- 处理嵌套结构
- 网页中的HTML标签常常存在嵌套关系,正则表达式可以处理一定程度的嵌套数据提取。
- 例如,要从一个包含评论列表的网页中提取每条评论及其回复。评论可能在
<div class="comment">
标签内,回复在<div class="reply">
标签内且嵌套在评论标签下。通过合适的正则表达式,可以逐层提取这些嵌套的数据。
(三)提高数据处理效率
- 快速匹配
- 正则表达式引擎经过优化,能够在大量文本中快速找到匹配的模式。在处理大型网页或大量网页时,这种快速匹配能力尤为重要。
- 例如,在爬取一个包含数千条产品信息的电商网站时,使用正则表达式可以快速扫描每个产品页面,提取诸如产品名称、价格、销量等关键信息,而不需要逐个字符去查找和判断。
- 减少代码复杂度
- 相较于手动编写复杂的字符串处理逻辑,使用正则表达式可以用简洁的模式表达复杂的匹配规则,从而减少代码量和复杂度。
- 比如,要从一个文本中提取所有的电话号码,手动编写代码可能需要多层循环和条件判断。而使用正则表达式
d{3}-d{4}-d{4}
(假设电话号码格式为XXX - XXXX - XXXX),可以用很少的代码实现相同的功能。
在Python中,re
模块提供了对正则表达式操作的支持,包括匹配、搜索、替换、分割等功能,使得在网络爬虫中方便地运用正则表达式来处理抓取到的数据。
二、正则表达式的内涵
在线正则表达式工具网站:在线正则表达式测试
正则表达式(Regular Expression)是一种用于描述、匹配和操作文本字符串的强大工具。它由一系列字符和操作符组成,可以定义一个搜索模式,用于在文本中查找、替换或验证符合特定模式的字符串。正则表达式在文本处理、数据验证、搜索引擎、编程语言等多个领域都有广泛应用。
(一)、常用元字符
- 普通字符
- 普通字符本身就匹配自身,例如
a
匹配字符a
,5
匹配数字5
。
- 普通字符本身就匹配自身,例如
- 特殊元字符
.
:匹配除换行符以外的任意字符。w
:匹配字母或数字或下划线。s
:匹配任意的空白符。d
:匹配数字。n
:匹配一个换行符。t
:匹配一个制表符。^
:匹配字符串的开始。$
:匹配字符串的结尾。W
:匹配非字母或数字或下划线。D
:匹配非数字。S
:匹配非空白符。a|b
:匹配字符a
或字符b
。( )
:匹配括号内的表达式,也表示一个组。[... ]
:匹配字符组中的字符。[^... ]
:匹配除了字符组中字符的所有字符。
(二)、量词(控制前面的元字符出现的次数)
*
:重复零次或更多次。+
:重复一次或更多次。?
:重复零次或一次。{n}
:重复n
次。{n,}
:重复n
次或更多次。{n,m}
:重复n
到m
次。
(三)、贪婪匹配和惰性匹配
- 贪婪匹配(
.*
)- 尽可能多地匹配字符。例如,对于字符串
"abcde"
,模式".*"
会匹配整个字符串。
- 尽可能多地匹配字符。例如,对于字符串
- 惰性匹配(
.*?
)- 尽可能少地匹配字符。例如,对于字符串
"abcde"
,模式".*?"
会匹配空字符串。
- 尽可能少地匹配字符。例如,对于字符串
(四)、Python网络爬虫中的常用正则表达式
- 匹配URL
- 例如,
http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+
可以匹配大多数HTTP和HTTPS的URL。
- 例如,
- 匹配电子邮件地址
- 例如,
^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$
可以匹配标准的电子邮件地址。
- 例如,
- 匹配IP地址
- 例如,
^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
可以匹配IPv4地址。
- 例如,
(五)、Python中的re模块
re.findall(pattern, string)
- 在字符串
string
中查找所有符合pattern
的子串,并返回一个列表。 - 例如:
import re lst = re.findall("m", "mai le fen, mai ni mei!") print(lst) # ['m', 'm', 'm']
- 在字符串
re.search(pattern, string)
- 在字符串
string
中查找第一个符合pattern
的子串,如果找到则返回一个匹配对象,否则返回None
。 - 例如:
ret = re.search("d", "5点之前,你要给我5000万").group() print(ret) # 5
- 在字符串
re.match(pattern, string)
- 从字符串的开头开始匹配,如果开头不符合
pattern
则返回None
。 - 例如:
ret = re.match("a", "abc").group() print(ret) # a
- 从字符串的开头开始匹配,如果开头不符合
re.finditer(pattern, string)
- 在字符串
string
中查找所有符合pattern
的子串,并返回一个迭代器。 - 例如:
it = re.finditer("m", "mai le fen, mai ni mei!") for match in it:print(match.group())
- 在字符串
三、典型案例
(一). 提取网页中的所有链接
- 使用
re.findall
和匹配URL的正则表达式可以从网页源代码中提取所有链接。 - 例如:
import re
import requestsurl = "https://www.example.com"
response = requests.get(url)
links = re.findall("http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", response.text)
print(links)
(二). 验证用户输入的电子邮件地址是否合法
- 使用匹配电子邮件地址的正则表达式可以验证用户输入。
- 例如:
import reemail = input("请输入你的电子邮件地址:")
if re.match("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$", email):print("电子邮件地址合法!")
else:print("电子邮件地址不合法!")
(三). 从文本中提取电话号码
- 使用合适的正则表达式可以从文本中提取电话号码。
- 例如:
import retext = "我的电话号码是13812345678,记得联系我。"
phone_numbers = re.findall("1[3-9]d{9}", text)
print(phone_numbers) # ['13812345678']
更多爬虫文章见专栏
Python网络爬虫