2011-05-06 36 views
1

你好 我有一个包含邮件地址的字符串。例如([email protected]) 和我有只包含域的列表(“bar.com”,“stackoverflow.com”)等在python中搜索列表中的字符串

我想搜索的列表,如果它包含了我字符串的域。现在我正在使用这样的代码

if tokens[1].partition("@")[2] in domainlist: 

tokens [1]包含邮件地址,domainlist包含域。 但正如你所看到的tokens[1].partition("@")[2]的结果将返回foo.bar.com,但我的名单有域bar.com。 如何让这个if语句返回true?它应该是非常快的,因为数以百计的电子邮件地址会在每一秒

+0

使用'.partition(“@”)[2]'将失败某些类型的电子邮件地址。有关如何操作,请参阅http://stackoverflow.com/questions/5908190/searching-a-string-in-a-list-in-python/5908265#5908265。 – ninjagecko 2011-05-06 07:59:49

回答

4

它应该是这样的:

if any(tokens[1].endswith(domain) for domain in domainlist): 
+1

太简单了,域'foo.com'也会匹配'somefoo.com' – 2011-05-06 07:52:55

+0

谢谢。它的工作原理与我想要的一样:) – Alptugay 2011-05-06 07:53:28

+0

抱歉,抱歉...它有一个问题...如果'bar.com'位于域列表中,它将返回'[email protected]'。可能不是什么OP要... :-( – eumiro 2011-05-06 07:55:12

1

首先,domainlist一套。检查是否包含某些内容会更快。其次,将所有“超级域名”添加到此集合中,如'bar.com'为'foo.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: 
1

数以百计的邮件地址不应该是一个问题。以下是一行:

any(domain.endswith(d) for d in MY_DOMAINS) 

在这里,你可以做user,sep,domain = address.rpartition('@')。否则,如果性能成为一个因素当前的方法将电子邮件地址,如"[email protected]"@something.com,根据http://tools.ietf.org/html/rfc5322

这是有效的失败,你可以使用一个特里(一种数据结构)。如果性能仍然是一个因素,您可以使用其他技巧。

上面介绍了您正在检查的域中的每个元素,因此如果您的列表中有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)) 
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 
2

如果速度真的是你的问题,你可以看看像Aho-Corasick这样的方法。有很多可用的实现,如esmre/esmhttp://code.google.com/p/esmre/

正如指出的@Riccardo加利,简单的字符串匹配会产生一些误报,所以你可以esmre先试,将根据正则表达式为指标,像index.enter("(^|\.){0}$".format(domain))