如何在Python行级清洗函数中实现Piping regex操作链,避免大量if/else
多轮正则流水清洗实现方案
错误原因说明
- 你之前使用的
.str是Pandas Series对象的专属向量化字符串处理方法,普通Python原生字符串没有该属性,因此触发AttributeError or逻辑不生效的原因是:当re.match匹配失败返回None时,直接调用.group()会先抛出异常,无法进入or的判断分支
解决方案
核心思路是将所有正则规则按执行顺序存入列表,遍历规则依次处理输入字符串,匹配失败则保留原串进入下一轮处理,无需编写大量if/else,后续新增规则只需追加到规则列表即可:
import re def shop_name_cleaning(shop_name): # 初始化当前处理字符串,统一转字符串并去除首尾空格 current = str(shop_name).strip() # 按执行顺序定义所有清洗规则 rules = [ # 规则1:去除www前缀 lambda s: re.match(r'(.*(?<!-))www\.(.*)', s).group(2).strip() if re.match(r'(.*(?<!-))www\.(.*)', s) else s, # 规则2:去除.com/.de/.co.uk等域名后缀 lambda s: re.match(r'(.*)\.(?=\bcom\b|\bde\b|\bit\b|\bco\.uk\b|\beu\b|\blv\b).*$', s).group(1).strip() if re.match(r'(.*)\.(?=\bcom\b|\bde\b|\bit\b|\bco\.uk\b|\beu\b|\blv\b).*$', s) else s, # 后续新增规则直接在此处追加即可,无需修改其他逻辑 # lambda s: 你的处理逻辑, ] # 遍历执行所有规则 for rule in rules: current = rule(current) return current
调用方式和你预期的完全一致:
test['identified_name'] = test.apply(lambda row: shop_name_cleaning(row['shopname']), axis=1)
简化写法(可选)
如果需要添加10+条规则,可封装工具函数简化规则定义,避免重复写正则匹配判断:
import re def regex_extract(pattern, group_idx=1, strip_result=True): """正则提取工具函数:匹配成功返回指定分组结果,失败返回原字符串""" def wrapper(s): match_res = re.match(pattern, s) if not match_res: return s extract_val = match_res.group(group_idx) return extract_val.strip() if strip_result else extract_val return wrapper def shop_name_cleaning(shop_name): current = str(shop_name).strip() # 规则定义大幅简化 rules = [ regex_extract(r'(.*(?<!-))www\.(.*)', group_idx=2), regex_extract(r'(.*)\.(?=\bcom\b|\bde\b|\bit\b|\bco\.uk\b|\beu\b|\blv\b).*$', group_idx=1), # 新增规则只需一行定义 # regex_extract(r'你的正则表达式', group_idx=要提取的分组序号), ] for rule in rules: current = rule(current) return current
内容的提问来源于stack exchange,提问作者Wingyan Yip
相关产品推荐
相关产品推荐

