Python 进阶详解:正则表达式与 JSON —— 文本处理与数据交换的核心技能

一、引言:为什么需要正则表达式和 JSON?

在现代编程中,正则表达式JSON是处理文本与数据的两大核心工具:

|-------------|-----------------------------------|
| 工具 | 核心用途 |
| ✅ 正则表达式 | 高效匹配、提取、替换复杂文本模式(如邮箱、手机号、日志解析) |
| ✅ JSON | 轻量级数据交换格式,广泛用于 Web API、配置文件、数据存储等 |

Python 提供了强大的内置模块:

  • re 模块:处理正则表达式
  • json 模块:实现 JSON 的编码与解码

掌握它们,你将具备数据清洗、接口通信、日志分析等关键能力!


二、正则表达式(Regular Expressions)

1. 什么是正则表达式?

正则表达式(Regex)是一种描述字符串模式的强大语法,可用于:

  • 🔍 验证输入:如邮箱、手机号、身份证号
  • 🧩 提取信息:从网页、日志中抓取关键数据
  • ✏️ 替换内容:批量修改文本
  • ✂️ 分割字符串:按复杂规则拆分文本

2. 基本语法与元字符

|-----------|-----------------------------|----------------------------------------|
| 元字符 | 说明 | 示例 |
| . | 匹配任意单个字符(除换行符) | a.c → "abc", "a2c" |
| ^ | 匹配字符串开头 | ^Hello→ "Hello World" ✅,"Hi Hello" ❌ |
| $ | 匹配字符串结尾 | world$→ "Hello world" ✅ |
| * | 前面字符出现 0 次或多次 | ab*c → "ac", "abc", "abbc" |
| + | 前面字符出现 1 次或多次 | ab+c → "abc", "abbc" ✅,"ac" ❌ |
| ? | 前面字符出现 0 次或 1 次 | colou?r → "color", "colour" |
| \d | 匹配数字(等价于 [0-9]) | \d{3} → "123" |
| \w | 匹配字母、数字、下划线([a-zA-Z0-9_]) | \w+ → "user_123" |
| \s | 匹配空白字符(空格、制表符、换行) | a\sb → "a b" |
| [...] | 匹配括号内任意一个字符 | [aeiou] → 匹配任一元音字母 |
| ( ... ) | 分组,用于捕获子表达式 | (\d{4})-(\d{2}) |


3. 使用 re 模块

3.1 导入模块
复制代码
import re

3.2 常用函数详解
re.match():从字符串开头匹配
复制代码
result = re.match(r'\d+', '123abc')
if result:
    print(result.group())  # 输出:123

⚠️ 注意match() 只检查开头,re.match(r'\d+', 'abc123') 返回 None


re.search():在整个字符串中搜索第一个匹配项
复制代码
result = re.search(r'\d+', 'abc123def')
if result:
    print(result.group())  # 输出:123

✅ 更常用,不局限于开头。


re.findall():返回所有匹配结果的列表
复制代码
matches = re.findall(r'\d+', 'abc123def456ghi')
print(matches)  # 输出:['123', '456']

✅ 简单直接,适合提取多个值。


re.finditer():返回匹配对象的迭代器(内存友好)
复制代码
for match in re.finditer(r'\d+', 'abc123def456ghi'):
    print(f"找到数字:{match.group()},位置:{match.span()}")
# 输出:
# 找到数字:123,位置:(3, 6)
# 找到数字:456,位置:(7, 10)

✅ 适合大文本处理,避免一次性加载所有结果。


re.sub():替换匹配的内容
复制代码
new_text = re.sub(r'\d+', 'NUM', 'abc123def456')
print(new_text)  # 输出:abcNUMdefNUM

# 支持函数替换
def double_num(match):
    num = int(match.group())
    return str(num * 2)

result = re.sub(r'\d+', double_num, '价格:100元和200元')
print(result)  # 输出:价格:200元和400元

re.split():使用正则表达式分割字符串
复制代码
parts = re.split(r'\s+', 'apple  banana   cherry')
print(parts)  # 输出:['apple', 'banana', 'cherry']

# 保留分隔符
parts_with_sep = re.split(r'(\s+)', 'apple  banana')
print(parts_with_sep)  # ['apple', '  ', 'banana']

4. 实际应用示例

✅ 验证邮箱格式
复制代码
def is_valid_email(email):
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, email) is not None

print(is_valid_email("user@example.com"))  # True
print(is_valid_email("invalid.email"))     # False

🔍 模式解析:

  • ^:开头
  • [a-zA-Z0-9._%+-]+:用户名(字母、数字、._%+-)
  • @:@ 符号
  • [a-zA-Z0-9.-]+:域名
  • \.:点号(转义)
  • [a-zA-Z]{2,}:顶级域名(至少2字母)
  • $:结尾

✅ 提取网页中的 URL
复制代码
text = "访问我们的网站 https://www.example.com 或 http://blog.example.org"
urls = re.findall(r'https?://[^\s]+', text)
print(urls)
# 输出:['https://www.example.com', 'http://blog.example.org']

🔍 模式解析:

  • https?:匹配 http 或 https
  • ://:协议分隔符
  • [^\s]+:非空白字符(直到空格或换行)

三、JSON(JavaScript Object Notation)

1. 什么是 JSON?

JSON 是一种轻量级的数据交换格式,基于文本,具有以下优点:

  • 👁️ 人类可读
  • 🤖 机器易解析
  • 🌐 跨语言支持(Python、JavaScript、Java 等)

2. JSON 支持的数据类型

|-----------------------|------------------|
| JSON 类型 | 对应 Python 类型 |
| 字符串 "hello" | str |
| 数字 42, 3.14 | int, float |
| 布尔值 true, false | True, False |
| null | None |
| 对象 {"key": "value"} | dict |
| 数组 ["a", "b"] | list |


3. JSON 示例

复制代码
{
  "name": "Alice",
  "age": 25,
  "is_student": false,
  "courses": ["数学", "英语"],
  "address": {
    "city": "北京",
    "zipcode": "100000"
  }
}

4. 使用 json 模块

4.1 导入模块
复制代码
import json

4.2 序列化:Python 对象 → JSON 字符串(json.dumps()
复制代码
data = {
    "name": "Bob",
    "age": 30,
    "hobbies": ["reading", "swimming"]
}

json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)

输出:

复制代码
{
  "name": "Bob",
  "age": 30,
  "hobbies": [
    "reading",
    "swimming"
  ]
}

✅ 参数说明:

  • ensure_ascii=False:允许输出中文(否则会转义)
  • indent=2:美化输出,2 空格缩进

4.3 反序列化:JSON 字符串 → Python 对象(json.loads()
复制代码
json_str = '{"name": "Charlie", "score": 95.5}'
data = json.loads(json_str)
print(data["name"])   # Charlie
print(data["score"])  # 95.5(float 类型)

4.4 读写 JSON 文件
写入文件
复制代码
with open("data.json", "w", encoding="utf-8") as file:
    json.dump(data, file, ensure_ascii=False, indent=2)

json.dump() 直接写入文件,无需先转字符串。


读取文件
复制代码
with open("data.json", "r", encoding="utf-8") as file:
    loaded_data = json.load(file)
    print(loaded_data)

json.load() 直接从文件读取并解析。


5. 实际应用示例:模拟 API 响应处理

复制代码
import json

# 模拟从 Web API 获取的 JSON 响应
api_response = '''
{
  "users": [
    {"id": 1, "name": "Alice", "email": "alice@example.com"},
    {"id": 2, "name": "Bob", "email": "bob@example.com"}
  ],
  "total": 2
}
'''

# 解析 JSON
response_data = json.loads(api_response)

# 提取用户信息
for user in response_data["users"]:
    print(f"用户: {user['name']}, 邮箱: {user['email']}")

输出:

复制代码
用户: Alice, 邮箱: alice@example.com
用户: Bob, 邮箱: bob@example.com

四、综合示例:日志分析器

结合正则表达式和 JSON,编写一个结构化日志分析器

复制代码
import re
import json

# 模拟日志行
log_line = '2025-08-04 10:30:15 ERROR User login failed for user=admin from IP=192.168.1.100'

# 使用正则提取信息
pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (\w+) (.+) from IP=(\d+\.\d+\.\d+\.\d+)'
match = re.match(pattern, log_line)

if match:
    timestamp, level, message, ip = match.groups()

    # 构建结构化数据
    log_entry = {
        "timestamp": timestamp,
        "level": level,
        "message": message,
        "ip": ip
    }

    # 转换为 JSON 字符串
    json_log = json.dumps(log_entry, ensure_ascii=False, indent=2)
    print(json_log)

输出:

复制代码
{
  "timestamp": "2025-08-04 10:30:15",
  "level": "ERROR",
  "message": "User login failed for user=admin",
  "ip": "192.168.1.100"
}

应用场景:日志收集、安全审计、系统监控。


五、总结:正则表达式与 JSON 的核心要点

|-----------|--------------|----------|------------------|
| 技术 | 核心用途 | 关键模块 | 推荐使用场景 |
| 正则表达式 | 文本模式匹配、提取、替换 | re | 验证输入、日志分析、爬虫数据提取 |
| JSON | 数据序列化与反序列化 | json | API 通信、配置文件、数据存储 |


六、最佳实践与建议

|-------------|--------------------------------------------|
| 建议 | 说明 |
| ✅ 正则表达式 | 使用 r''原始字符串避免转义问题 |
| ✅ 调试正则 | 使用 regex101.com 在线测试 |
| ✅ 处理异常 | json.loads() 可能抛出 json.JSONDecodeError |
| ✅ 编码处理 | 读写 JSON 文件时指定 encoding="utf-8" |
| ✅ 性能优化 | 复用正则模式:pattern = re.compile(r'\d+') |


七、动手练习

1. 验证手机号(如 13812345678)

复制代码
def is_valid_phone(phone):
    # 中国大陆手机号:1 开头,第二位 3-9,共 11 位
    pattern = r'^1[3-9]\d{9}$'
    return re.match(pattern, phone) is not None

print(is_valid_phone("13812345678"))  # True
print(is_valid_phone("12345678901"))  # False

2. 保存个人信息为 JSON 文件

复制代码
import json

profile = {
    "name": "张三",
    "age": 28,
    "city": "上海",
    "skills": ["Python", "数据分析", "Web 开发"]
}

with open("profile.json", "w", encoding="utf-8") as file:
    json.dump(profile, file, ensure_ascii=False, indent=2)

print("个人信息已保存到 profile.json")

3. 分析日志文件并输出 JSON

假设 logs.txt 内容:

复制代码
2025-08-04 10:00:00 INFO System started
2025-08-04 10:01:23 ERROR Database connection failed
2025-08-04 10:02:45 WARNING Disk usage high

import re
import json

pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (\w+) (.+)'

error_logs = []

with open("logs.txt", "r", encoding="utf-8") as file:
    for line in file:
        match = re.match(pattern, line.strip())
        if match:
            timestamp, level, message = match.groups()
            if level == "ERROR":
                error_logs.append({
                    "timestamp": timestamp,
                    "level": level,
                    "message": message
                })

# 输出为 JSON
json_output = json.dumps(error_logs, ensure_ascii=False, indent=2)
print(json_output)

🚀 学习建议

  1. 多练习正则:从简单模式开始,逐步构建复杂表达式。
  2. 理解 JSON 结构:熟悉嵌套对象与数组的处理。
  3. 结合使用:在真实项目中,常需用正则清洗原始数据,再组织成 JSON。
  4. 进阶学习
    • 正则的贪婪 vs 非贪婪 模式(*?, +?
    • json 模块的 cls 参数(自定义编码器)
    • 使用 pathlibjson 构建配置管理器