pin_drop当前位置:知识文库 ❯ 图文
Python正则表达式常用模式 - 邮箱手机号URL验证大全
一、邮箱地址匹配
邮箱地址是最常见的需要验证的数据格式之一。一个标准的邮箱地址由用户名、@符号和域名三部分组成。
代码示例
import re
# 基础邮箱匹配模式
email_pattern = r"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+"
# 测试邮箱地址
emails = [
"user@example.com", # 有效
"test.user@company.co.uk", # 有效
"admin@sub.domain.org", # 有效
"invalid-email", # 无效
"@missing.com", # 无效
"user@.com", # 无效
]
for email in emails:
match = re.fullmatch(email_pattern, email)
status = "有效" if match else "无效"
print(f"{email}: {status}")
更严格的邮箱验证模式,符合RFC 5322标准:
代码示例
import re
# 严格邮箱匹配(支持更多合法字符)
strict_email = r"(?P<local>[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+)@(?P<domain>[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)"
def validate_email(email):
match = re.fullmatch(strict_email, email)
if match:
return {
"valid": True,
"local": match.group("local"),
"domain": match.group("domain")
}
return {"valid": False}
# 测试
result = validate_email("hello.world@gmail.com")
print(result)
# {'valid': True, 'local': 'hello.world', 'domain': 'gmail.com'}
二、手机号码验证
中国大陆手机号码以1开头,第二位通常为3-9,总共11位数字。以下是常用的手机号验证模式:
代码示例
import re
# 中国大陆手机号验证
phone_pattern = r"^1[3-9]\d{9}$"
phones = [
"13800138000", # 有效 - 移动
"15912345678", # 有效 - 联通
"18612345678", # 有效 - 电信
"12345678901", # 无效 - 第二位不是3-9
"1380013800", # 无效 - 位数不够
"138001380001", # 无效 - 位数过多
]
for phone in phones:
match = re.match(phone_pattern, phone)
print(f"{phone}: {'有效' if match else '无效'}")
代码示例
import re
# 更详细的运营商识别
def identify_carrier(phone):
if not re.match(r"^1[3-9]\d{9}$", phone):
return "无效的手机号码"
prefix = phone[:3]
carrier_map = {
"134": "移动", "135": "移动", "136": "移动", "137": "移动", "138": "移动", "139": "移动",
"150": "移动", "151": "移动", "152": "移动", "157": "移动", "158": "移动", "159": "移动",
"130": "联通", "131": "联通", "132": "联通", "155": "联通", "156": "联通", "185": "联通", "186": "联通",
"133": "电信", "153": "电信", "180": "电信", "181": "电信", "189": "电信",
}
return carrier_map.get(prefix, "未知运营商")
print(identify_carrier("13800138000")) # 移动
print(identify_carrier("18612345678")) # 联通
print(identify_carrier("18912345678")) # 电信
三、URL链接匹配
URL匹配需要考虑协议、域名、端口、路径和查询参数等多个部分。
代码示例
import re
# 匹配完整URL
url_pattern = r"(?P<protocol>https?|ftp)://(?P<host>[^\s:/]+)(?::(?P<port>\d+))?(?P<path>/[^\s?]*)?(?:\?(?P<query>[^\s#]*))?"
urls = [
"https://www.example.com",
"http://api.test.com:8080/v1/users?page=1&size=10",
"ftp://files.server.com/docs/report.pdf",
"https://example.com/path/to/page#section1",
]
for url in urls:
match = re.search(url_pattern, url)
if match:
d = match.groupdict()
print(f"协议: {d['protocol']}, 主机: {d['host']}, 端口: {d['port'] or '默认'}")
print(f" 路径: {d['path'] or '/'}, 参数: {d['query'] or '无'}")
print()
代码示例
import re
# 从文本中提取所有URL
text = """
访问我们的网站 https://www.example.com 或
API文档 http://api.example.com/docs
FTP服务器 ftp://ftp.example.com/pub
"""
# 简单的URL提取模式
extract_pattern = r"https?://[^\s<>\"]+|ftp://[^\s<>\"]+"
urls_found = re.findall(extract_pattern, text)
for url in urls_found:
print(url)
四、IP地址匹配
IPv4地址由4个0-255之间的数字组成,用点号分隔。精确匹配需要确保每个段的数值范围正确。
代码示例
import re
# 精确的IPv4地址匹配
ipv4_pattern = r"^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$"
ips = [
"192.168.1.1", # 有效
"10.0.0.1", # 有效
"255.255.255.255", # 有效
"256.1.2.3", # 无效 - 256超出范围
"192.168.1", # 无效 - 只有3段
"192.168.01.1", # 无效 - 有前导零
]
for ip in ips:
match = re.match(ipv4_pattern, ip)
print(f"{ip}: {'有效' if match else '无效'}")
代码示例
import re
# IPv6地址匹配(简化版)
ipv6_pattern = r"^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"
ipv6_addresses = [
"2001:0db8:85a3:0000:0000:8a2e:0370:7334", # 有效
"::1", # 有效(简化形式)
"fe80::1", # 有效(简化形式)
"2001:db8::8a2e:370:7334", # 有效(简化形式)
]
# 完整的IPv6模式较为复杂,以上为简化匹配
# 实际项目中建议使用 ipaddress 模块进行验证
import ipaddress
def validate_ipv6(addr):
try:
ipaddress.IPv6Address(addr)
return True
except ValueError:
return False
for addr in ipv6_addresses:
print(f"{addr}: {'有效' if validate_ipv6(addr) else '无效'}")
五、身份证号验证
中国大陆身份证号有15位(旧版)和18位(新版)两种格式,18位身份证最后一位可能是数字或X。
代码示例
import re
# 身份证号基本格式验证
id_card_pattern = r"^\d{17}[\dXx]$|^\d{15}$"
id_cards = [
"11010519491231002X", # 有效 - 18位
"110105194912310021", # 有效 - 18位
"110105491231002", # 有效 - 15位
"11010519491231002", # 无效 - 17位
"11010519491231002Y", # 无效 - 最后一位不是X
]
for card in id_cards:
match = re.match(id_card_pattern, card)
print(f"{card}: {'有效' if match else '无效'}")
代码示例
import re
# 更详细的身份证信息提取
def parse_id_card(id_card):
if not re.match(r"^\d{17}[\dXx]$", id_card):
return None
area = id_card[:6]
birth_year = id_card[6:10]
birth_month = id_card[10:12]
birth_day = id_card[12:14]
gender = "男" if int(id_card[16]) % 2 == 1 else "女"
check_code = id_card[17].upper()
return {
"地区码": area,
"出生日期": f"{birth_year}-{birth_month}-{birth_day}",
"性别": gender,
"校验码": check_code
}
info = parse_id_card("110105199001011234")
for key, value in info.items():
print(f"{key}: {value}")
六、其他常用模式汇总
代码示例
import re
# 常用模式字典,方便直接调用
PATTERNS = {
"email": r"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+",
"phone": r"^1[3-9]\d{9}$",
"ipv4": r"^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$",
"postal_code": r"^\d{6}$",
"username": r"^[a-zA-Z0-9_]{4,16}$",
"date": r"^\d{4}-\d{2}-\d{2}$",
"time": r"^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$",
"hex_color": r"^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$",
}
def validate(pattern_name, value):
"""通用验证函数"""
pattern = PATTERNS.get(pattern_name)
if not pattern:
return False
return bool(re.fullmatch(pattern, value))
# 使用示例
print(validate("email", "test@example.com")) # True
print(validate("phone", "13800138000")) # True
print(validate("ipv4", "192.168.1.1")) # True
print(validate("postal_code", "100000")) # True
print(validate("hex_color", "#2196F3")) # True
小贴士
正则表达式虽然强大,但对于复杂的数据验证(如身份证号校验码、邮箱RFC标准等),建议结合专用库使用。Python内置的 ipaddress 模块可以替代正则验证IP地址,email_validator 库可以更准确地验证邮箱。
注意:以上模式仅做格式校验,不验证数据的真实性。例如手机号正则只能验证格式是否正确,不能确认该号码是否存在。实际业务中需要结合短信验证码、API接口等方式进行二次验证。
常见问题
邮箱正则表达式为什么看起来这么复杂?
因为RFC 5322标准对邮箱地址的定义非常灵活,用户名部分可以包含字母、数字以及多种特殊字符(.!#$%&'*+/=?^_`{|}~-)。简单模式可能漏掉合法邮箱或接受非法格式,需要根据实际需求在简洁和严格之间取舍。
如何验证身份证号的合法性(不仅是格式)?
18位身份证最后一位是校验码,可以通过前17位按照ISO 7064:1983.MOD 11-2算法计算得出。完整的验证需要:1)校验格式 2)校验出生日期合法性 3)校验校验码是否正确。建议使用第三方库如 id-validator。
为什么IP地址验证不使用简单的 \d+\.\d+\.\d+\.\d+?
因为 \d+ 会匹配任意长度的数字,像 999.999.999.999 也会被匹配,但这不是合法的IP地址。每个段必须在0-255范围内,所以需要使用 (25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d) 来精确匹配。
密码验证正则是如何工作的?
(?=.*[A-Za-z]) 是正向先行断言,确保至少包含一个字母;(?=.*\d) 确保至少包含一个数字;[A-Za-z\d]{8,} 规定只能包含字母和数字且长度至少8位。这些条件通过先行断言组合在一起。
练习1
编写一个函数,接收一段文本,提取其中所有的邮箱地址和手机号,并返回分类后的结果字典。
练习2
创建一个表单验证类,使用正则表达式验证用户输入的用户名、密码、邮箱和手机号,返回详细的错误信息。
本文涉及AI创作
内容由AI创作,请仔细甄别