正则表达式是文本处理的瑞士军刀,在数据清洗、表单验证、日志分析等场景中不可或缺。下面我将通过四个典型场景,带你掌握如何用Python的re模块构建精准匹配规则。
陕西地区固定电话的区号格式为029-XXXXXXX,我们需要验证输入是否符合这一规范:
python复制"陕西区号": r"^029-\d+$"
这个正则表达式的核心要素:
^ 表示字符串开始,确保没有前缀字符029- 是字面匹配,必须精确出现\d+ 匹配1个或多个数字(+量词)$ 表示字符串结束,防止后面有多余字符实际应用中建议限制号码长度,如
\d{7,8}匹配7-8位号码,避免匹配到超长错误输入
中国邮政编码是6位纯数字,这个规则看似简单但有几个注意点:
python复制"邮政编码": r"^\d{6}$"
关键细节:
{6}精确匹配6位数字,比+或*更严格[1-9]\d{5}邮箱格式相对复杂,需要兼顾通用性和安全性:
python复制"邮箱": r"^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$"
这个正则做了以下设计:
@符号作为分隔符mail.xjtu.edu.cn).com等)商业级应用建议使用
email-validator库,RFC标准正则非常复杂
18位身份证号校验需要同时考虑格式和校验位:
python复制"身份证号": r"^\d{17}[\dXx]$"
进阶校验方案:
python复制def validate_id_number(id_num):
# 基本格式校验
if not re.fullmatch(r"^\d{17}[\dXx]$", id_num):
return False
# 校验码计算
factor = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]
check_codes = "10X98765432"
total = sum(int(a)*b for a,b in zip(id_num[:17], factor))
return id_num[-1].upper() == check_codes[total % 11]
我们使用requests+BeautifulSoup组合实现图片爬取,关键点包括:
python复制def crawl_school_images(url, save_file="img_urls.txt"):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
}
try:
response = requests.get(url, headers=headers, timeout=10)
soup = BeautifulSoup(response.text, "html.parser")
img_urls = []
for img in soup.find_all("img"):
img_src = img.get("src")
if img_src:
# URL标准化处理
if img_src.startswith("//"):
img_src = "https:" + img_src
elif not img_src.startswith(("http", "https")):
img_src = urljoin(url, img_src)
img_urls.append(img_src)
# 结果存储
with open(save_file, "w", encoding="utf-8") as f:
f.write("\n".join(img_urls))
return img_urls
装饰器为爬虫添加了执行监控能力:
python复制def crawl_logger(func):
def wrapper(url, *args, **kwargs):
start_time = datetime.now()
print(f"开始爬取:{start_time.strftime('%Y-%m-%d %H:%M:%S')}")
img_urls = func(url, *args, **kwargs)
log_info = f"""
耗时:{(datetime.now() - start_time).total_seconds():.2f}秒
图片数量:{len(img_urls)}
目标网址:{url}
"""
with open("crawl_log.txt", "a") as f:
f.write(log_info)
return img_urls
return wrapper
生产环境爬虫还需要考虑:
异常处理增强
性能优化
python复制# 使用Session保持连接
session = requests.Session()
response = session.get(url)
# 异步爬取(aiohttp+asyncio)
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
html = await resp.text()
反爬对抗策略
在线测试工具推荐
调试方法
python复制# 编译时开启调试标志
re.compile(pattern, re.DEBUG)
# 分步测试复杂正则
phone_re = re.compile(r"""
^ # 字符串开始
(029) # 区号分组
- # 分隔符
(\d{7,8}) # 号码分组
$ # 字符串结束
""", re.VERBOSE)
动态加载内容处理
图片URL处理经验
python复制# 常见问题案例
img_src = "data:image/png;base64,..." # Base64内嵌图片
img_src = "javascript:void(0)" # 无效JS链接
img_src = "//example.com/img.jpg" # 协议相对URL
法律合规要点
分组提取数据
python复制# 提取区号和号码
match = re.fullmatch(r"^(029)-(\d+)$", "029-87654321")
area_code, number = match.groups()
替换与分割
python复制# 模糊匹配替换
text = "联系:029-12345或029-67890"
re.sub(r"029-\d+", "[区号屏蔽]", text)
图片下载器改进
python复制def download_image(url, save_dir):
response = requests.get(url, stream=True)
file_name = os.path.join(save_dir, url.split("/")[-1])
with open(file_name, "wb") as f:
for chunk in response.iter_content(1024):
f.write(chunk)
Scrapy框架迁移
在实际项目中,我建议先用小规模测试验证正则表达式的准确性,再应用到生产环境。爬虫开发时要特别注意网络请求的健壮性处理,添加足够的异常捕获和重试机制。