您好 我有一个包含邮件地址的字符串。例如(user@foo.bar.com) 我有一个只包含域名的列表('bar.com','stackoverflow.com')等。
如果它包含我的字符串域,我想搜索列表。现在我正在使用像这样的代码
if tokens[1].partition("@")[2] in domainlist:
令牌[1]包含邮件地址,域列表包含域。
但正如您所见,tokens[1].partition("@")[2]
的结果将返回foo.bar.com
,但我的列表中包含域bar.com
。
如何使if语句返回true?它应该非常快,因为每秒都有数百个邮件地址
答案 0 :(得分:4)
它应该像这样工作:
if any(tokens[1].endswith(domain) for domain in domainlist):
答案 1 :(得分:2)
如果速度真的是你的问题,你可以研究像Aho-Corasick这样的方法。有很多可用的实现,例如esmre
/ esm
http://code.google.com/p/esmre/
正如@Riccardo Galli所指出的,简单的字符串匹配会产生一些误报,因此您可以先使用esmre
进行尝试,将正则表达式添加到索引中,例如index.enter("(^|\.){0}$".format(domain))
答案 2 :(得分:1)
首先,将domainlist
设为一组。检查是否包含某些内容会更快。
其次,将所有“超级域名”添加到此集合中,例如“foo.bar.com”的“bar.com”。
domainlist = ['foo.bar.com', 'bar2.com', 'foo3.bar3.foobar.com']
domainset = set()
for domain in domainlist:
parts = domain.split('.')
domainset.update('.'.join(parts[i:]) for i in xrange(len(parts)-1))
#domainset is now:
set(['bar.com',
'bar2.com',
'bar3.foobar.com',
'foo.bar.com',
'foo3.bar3.foobar.com',
'foobar.com'])
现在你可以测试了
if tokens[1].partition("@")[2] in domainset:
答案 3 :(得分:1)
数百个邮件地址不应成为问题。以下是单行:
any(domain.endswith(d) for d in MY_DOMAINS)
在这里,您可以user,sep,domain = address.rpartition('@')
。否则,对于"B@tm4n"@something.com
等电子邮件地址,您的当前方法将失败,这些地址根据http://tools.ietf.org/html/rfc5322
如果性能成为一个因素,您可以使用Trie(一种数据结构)。如果表现仍然是一个因素,你可以使用其他技巧。
上面介绍了您正在检查的域中的每个元素,因此如果列表中有1000个域,则需要为每个电子邮件地址执行1000次查找。如果这是一个问题,您可以执行此操作以实现每次查找O(1)
(您还可能希望确保不检查超过5个后缀,以保护自己免受恶意制作的电子邮件地址)。
MY_DOMAINS = set(MY_DOMAINS)
def suffixes(domain):
"""
suffixes('foo.bar.com') -yields-> ['foo.bar.com', 'bar.com', 'com']
"""
while True:
yield domain
parts = domain.split('.',1)
if len(parts>1)
domain = parts[1]
else:
break
def isInList(address):
user,sep,domain = address.rpartition('@')
return any(suffix in MY_DOMAINS for suffix in suffixes(domain))
答案 4 :(得分:1)
与其他答案相反,这里'foo.com'也不会与'@ y.afoo.com'相匹配
def mailInDomains(mail,domains):
for domain in domainList:
dLen = len(domain)
if mail[-dLen:]==domain and mail[-dLen-1] in ('.','@'):
return True
return False