能否将提取Twitter用户名的两个正则表达式合并为一个?
简化Twitter用户名提取的正则表达式
我目前用两个正则表达式从字符串中提取Twitter用户名,现有代码如下:
def get_username(string): p1 = re.compile(r'twitter\.com/([a-z0-9_\.\-]+)', re.IGNORECASE) p2 = re.compile(r'twitter[\s\:@]+([a-z0-9_\.\-]+)', re.IGNORECASE) match1 = re.search(p1, string) match2 = re.search(p2, string) if match1: return match1.group(1) elif match2: return match2.group(1) else: return None
测试示例
get_username("Twitter: https://twitter.com/foo123") get_username("Twitter: twitter.com/foo123") get_username("https://twitter.com/foo123") get_username("https://twitter.com/foo123?blah") get_username("Twitter foo123") get_username("Twitter @foo123") get_username("Twitter: foo123") get_username("Twitter: foo123 | youtube: ...")
我尝试将两个正则合并为一个,写出了如下表达式:
pattern = re.compile(r'twitter(?:(?:\.com/)|(?:[\s\:@]+))([a-z0-9_\.\-]+)', re.IGNORECASE)
但这个方案在第一个测试示例中失效——字符串里的Twitter: https会先被匹配,导致提取出错误内容,而非目标用户名foo123。
解决方法
可以通过分支优先级实现原逻辑的合并:优先匹配带.com/的Twitter链接(包含可选的http/https前缀),再匹配纯提及式的用户名。修改后的代码如下:
def get_username(string): # 先匹配Twitter链接格式,再匹配提及/关联格式 pattern = re.compile(r'(?:https?://)?twitter\.com/([a-z0-9_\.\-]+)|twitter[\s\:@]+([a-z0-9_\.\-]+)', re.IGNORECASE) match = re.search(pattern, string) if match: # 优先取第一个分支的结果,无则取第二个分支 return match.group(1) or match.group(2) return None
说明
- 第一个分支
(?:https?://)?twitter\.com/([a-z0-9_\.\-]+):匹配带可选协议的Twitter个人主页链接,提取用户名 - 第二个分支
twitter[\s\:@]+([a-z0-9_\.\-]+):匹配Twitter @用户名、Twitter: 用户名这类提及格式 re.search会按分支顺序匹配,优先找到链接格式的匹配;若没有则匹配提及格式,和原代码逻辑完全一致- 通过
match.group(1) or match.group(2)取第一个有值的分组结果,实现原代码的优先级判断
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

