2011-05-06 51 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))