文章目录
-
- [1. 正则表达式基础](#1. 正则表达式基础)
-
- [1.1 常用元字符](#1.1 常用元字符)
- [1.2 基本用法](#1.2 基本用法)
- [2. 正则表达式高级功能](#2. 正则表达式高级功能)
-
- [2.1 分组捕获](#2.1 分组捕获)
- [2.2 命名分组](#2.2 命名分组)
- [2.3 非贪婪匹配](#2.3 非贪婪匹配)
- [2.4 零宽断言](#2.4 零宽断言)
- [2.5 编译正则表达式](#2.5 编译正则表达式)
- [2.6 转义字符](#2.6 转义字符)
- [3. 常见应用场景](#3. 常见应用场景)
-
- [3.1 验证邮箱格式](#3.1 验证邮箱格式)
- [3.2 提取 URL](#3.2 提取 URL)
- [3.3 提取日期](#3.3 提取日期)
- [3.4 提取HTML中的链接](#3.4 提取HTML中的链接)
- [3.5 提取HTML中的图片链接](#3.5 提取HTML中的图片链接)
- [3.6 提取JSON中的特定字段](#3.6 提取JSON中的特定字段)
- [4. 总结](#4. 总结)
在Python爬虫中, 正则表达式
( Regular Expression,简称Regex
)是一种强大的工具,用于从文本中提取、匹配和替换特定的字符串模式。正则表达式可以帮助我们从HTML、JSON等格式的文本中提取所需的数据。
1. 正则表达式基础
1.1 常用元字符
正则表达式由一系列字符和特殊符号组成,用于定义匹配模式。以下是一些常用的正则表达式元字符:
.
匹配任意字符(除了换行符 \n)^
匹配字符串的开头$
匹配字符串的结尾*
匹配前面的字符 0 次或多次+
匹配前面的字符 1 次或多次?
匹配前面的字符 0 次或 1 次{n}
匹配前面的字符恰好 n 次{n,}
匹配前面的字符至少 n 次{n,m}
匹配前面的字符至少 n 次,至多 m 次\d
匹配数字(等价于 [0-9])\D
匹配非数字(等价于 [^0-9])\w
匹配字母、数字或下划线(等价于 [a-zA-Z0-9_])\W
匹配非字母、数字或下划线\s
匹配空白字符(空格、制表符、换行符等)\S
匹配非空白字符[...]
匹配括号内的任意一个字符[^...]
匹配不在括号内的任意一个字符
1.2 基本用法
Python提供了re模块来支持正则表达式的操作。以下是re模块中常用的函数:
re.search(pattern, string)
:在字符串中搜索匹配正则表达式的第一个位置,返回一个匹配对象。如果没有匹配项,返回None。re.match(pattern, string)
:从字符串的开头开始匹配正则表达式,返回一个匹配对象。如果没有匹配项,返回None。re.findall(pattern, string)
:返回字符串中所有匹配正则表达式的子串,返回一个列表。re.sub(pattern, repl, string)
:将字符串中所有匹配正则表达式的子串替换为repl,返回替换后的字符串。re.compile(pattern)
:将正则表达式编译为一个正则表达式对象,可以重复使用。
Python 的 re 模块使用样例如下:
python
import re
# re.match()
result = re.match(r'hello', 'hello world')
if result:
print("匹配成功:", result.group()) # 输出: 匹配成功: hello
else:
print("匹配失败")
# re.search()
result = re.search(r'world', 'hello world')
if result:
print("匹配成功:", result.group()) # 输出: 匹配成功: world
else:
print("匹配失败")
# re.findall()
result = re.findall(r'\d+', '3 apples, 5 bananas, 10 cherries')
print(result) # 输出: ['3', '5', '10']
#re.finditer()
matches = re.finditer(r'\d+', '3 apples, 5 bananas, 10 cherries')
for match in matches:
print(match.group()) # 输出: 3, 5, 10
# re.sub()
text = '3 apples, 5 bananas, 10 cherries'
result = re.sub(r'\d+', 'X', text)
print(result) # 输出: X apples, X bananas, X cherries
# re.split()
result = re.split(r'\s+', 'hello world')
print(result) # 输出: ['hello', 'world']
2. 正则表达式高级功能
2.1 分组捕获
使用 () 可以将匹配的内容分组,并通过 group() 方法获取。
python
import re
text = 'John: 30, Jane: 25'
result = re.search(r'(\w+): (\d+)', text)
if result:
print("姓名:", result.group(1)) # 输出: 姓名: John
print("年龄:", result.group(2)) # 输出: 年龄: 30
2.2 命名分组
可以为分组命名,方便后续引用。
python
import re
text = 'John: 30'
result = re.search(r'(?P<name>\w+): (?P<age>\d+)', text)
if result:
print("姓名:", result.group('name')) # 输出: 姓名: John
print("年龄:", result.group('age')) # 输出: 年龄: 30
2.3 非贪婪匹配
正则表达式默认是贪婪匹配,即尽可能多地匹配字符。例如,.*
会匹配尽可能多的字符。可以使用.*?
进行非贪婪匹配。
python
import re
text = '<div>content1</div><div>content2</div>'
result = re.findall(r'<div>(.*?)</div>', text)
print(result) # 输出: ['content1', 'content2']
2.4 零宽断言
零宽断言用于指定匹配的位置,但不消耗字符。
- 正向先行断言:(?=...),匹配后面是 ... 的位置。
- 负向先行断言:(?!..),匹配后面不是 ... 的位置。
- 正向后行断言:(?<=...),匹配前面是 ... 的位置。
- 负向后行断言:(?<!..),匹配前面不是 ... 的位置。
python
import re
# 匹配后面是数字的字母
result = re.findall(r'\w+(?=\d)', 'apple3 banana5 cherry10')
print(result) # 输出: ['apple', 'banana', 'cherry']
# 匹配前面是数字的字母
result = re.findall(r'(?<=\d)\w+', '3apple 5banana 10cherry')
print(result) # 输出: ['apple', 'banana', 'cherry']
2.5 编译正则表达式
如果需要多次使用同一个正则表达式,可以将其编译为 re.Pattern 对象,以提高效率。
python
import re
pattern = re.compile(r'\d+')
result = pattern.findall('3 apples, 5 bananas, 10 cherries')
print(result) # 输出: ['3', '5', '10']
2.6 转义字符
在正则表达式中,某些字符(如.、*、?等)具有特殊含义。如果要匹配这些字符本身,需要使用反斜杠\进行转义。例如,.匹配实际的.字符。
3. 常见应用场景
3.1 验证邮箱格式
python
import re
def validate_email(email):
pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
return re.match(pattern, email) is not None
print(validate_email('test@example.com')) # 输出: True
print(validate_email('invalid-email')) # 输出: False
3.2 提取 URL
python
import re
text = 'Visit https://www.example.com or http://example.org'
urls = re.findall(r'https?://[^\s]+', text)
print(urls) # 输出: ['https://www.example.com', 'http://example.org']
3.3 提取日期
python
import re
text = 'Today is 2023-10-05, and tomorrow is 2023-10-06.'
dates = re.findall(r'\d{4}-\d{2}-\d{2}', text)
print(dates) # 输出: ['2023-10-05', '2023-10-06']
3.4 提取HTML中的链接
假设我们要从HTML中提取所有的链接,可以使用正则表达式来匹配标签中的href属性。
python
import re
html = """
<a href="https://www.example.com">Example</a>
<a href="https://www.google.com">Google</a>
<a href="https://www.python.org">Python</a>
"""
# 正则表达式匹配<a>标签中的href属性
pattern = r'<a href="(.*?)">'
# 使用re.findall提取所有匹配的链接
links = re.findall(pattern, html)
print(links)
# 输出:['https://www.example.com', 'https://www.google.com', 'https://www.python.org']
3.5 提取HTML中的图片链接
假设我们要从HTML中提取所有的图片链接,可以使用正则表达式来匹配标签中的src属性。
python
import re
html = """
<img src="https://www.example.com/image1.jpg" alt="Image 1">
<img src="https://www.google.com/logo.png" alt="Google Logo">
<img src="https://www.python.org/python.png" alt="Python Logo">
"""
# 正则表达式匹配<img>标签中的src属性
pattern = r'<img src="(.*?)"'
# 使用re.findall提取所有匹配的图片链接
image_links = re.findall(pattern, html)
print(image_links)
# 输出:['https://www.example.com/image1.jpg', 'https://www.google.com/logo.png', 'https://www.python.org/python.png']
3.6 提取JSON中的特定字段
假设我们有一个JSON字符串,想要提取其中的某个字段,可以使用正则表达式来匹配。
python
import re
json_data = '{"name": "Alice", "age": 25, "city": "New York"}'
# 正则表达式匹配"name"字段的值
pattern = r'"name": "(.*?)"'
# 使用re.search提取匹配的字段值
match = re.search(pattern, json_data)
if match:
print(match.group(1))
4. 总结
正则表达式是处理文本的强大工具,Python 的 re 模块提供了丰富的功能来支持正则表达式的使用。通过掌握基础语法和高级功能,可以轻松应对各种文本处理任务。