在Python中过滤电子邮件和域名的最佳方法

3 投票
3 回答
3924 浏览
提问于 2025-04-17 05:59

我有一份电子邮件和域名的列表,我想把它们作为黑名单来过滤掉。

对于电子邮件来说,这很简单,因为我可以直接比较电子邮件。但对于域名来说,像带有子域名的电子邮件也需要一起匹配。

比如说,对于foo.com这个域名,我需要过滤掉:

x@foo.com
x@subdomain.foo.com

通常是怎么做的呢?是用正则表达式吗?还是把电子邮件拆分成合适的字符串来处理?

3 个回答

0

那这个怎么样呢

.*foo\.com$

这样可以吗?

1

这是我能想到的最简单的方法:

>>> f = 'foo@subdomain.bar.com'
>>> '.'.join(f.split('.')[-2:])
'bar.com'

这个方法不使用正则表达式,只用了一行代码,非常容易理解。它可以提取出域名,而且不管这个域名是 .com、.net 还是其他的,都没关系。

然后你只需要把提取出来的域名和你的黑名单进行对比就可以了。

编辑: 好吧,对于 .co.uk 这样的域名等等

>>> import re
>>> def get_addr(email_addr):
        parts = re.split(r'[\@\.]', email_addr)
        return '.'.join(parts[(-3 if parts[-2] == 'co' else -2):])
>>> get_addr('foo@subdomain.bar.com')
'bar.com'
>>> get_addr('foo@subdomain.bar.co.uk')
'bar.co.uk'
>>> get_addr('foo@bar.com')
'bar.com'

编辑: @Wilduck 提到可能有一些情况,你想要过滤掉特定的子域名,但不想过滤其他的(比如 'community.ebay.co.uk')。我想,你可能也想要把特定的邮箱地址加入黑名单,而不需要单独建立一个表(比如 exgirlfriend@gmail.com)。这是我的解决方案:

>>> def is_in_blacklist(addr):
...     #check if addr is in your list or db table
...     return True or False

>>> def addr_is_blacklisted(addr):
...     if not addr: return False
...     if is_in_blacklist(addr):
...         return True
...     sliced = '.'.join(addr.split('@' if '@' in addr else '.')[1:])
...     return addr_is_blacklisted(sliced)

这个方法是从头到尾拆解邮箱地址,并检查每个部分是否在你的黑名单中。显然,你不能通过一次查询就得到答案,但你可以逐个邮箱地址、子域名、域名,甚至顶级域名进行过滤。如果你愿意的话。平均来说,每个邮箱大约需要 3-4 次查询,如果你的黑名单很大,也不会让你崩溃。

6

我觉得最简单的方法是用 字符串方法 ends_with。这个方法的工作原理是这样的:

>>> blacklisted = 'foo.com'
>>> email = 'x@foo.com'
>>> email.endswith('foo.com')
True
>>> email = 'x@subdomain.foo.com'
>>> email.endswith('foo.com')
True

如果域名、邮箱或者其他东西以 'foo.com' 结尾,它就会返回真。你可以看到,这个方法会包括所有 'foo.com' 的子域名。更方便的是,你还可以把一个元组传给 endswith,所以如果你把黑名单域名放在一个元组里,你可以这样做:

>>> blacklisted = ('foo.com', 'bar.com')
>>> email = 'x@bar.com'
>>> email.endswith(blacklisted)
True

这样你甚至可以选择性地屏蔽一些子域名,而不是其他的。

>>> blacklisted = ('foo.com', 'bar.com', 'sub.baz.net')
>>> email_bad = 'x@sub.baz.net'
>>> email_bad.endswith(blacklisted)
True
>>> email_good = 'x@good.baz.net'
>>> email_good.endswith(blacklisted)
False

编辑: 针对 Avaris 的评论:

为了确保你不会遇到这种情况:

>>> blacklisted = ('bar.com', 'baz.com')
>>> email = 'x@foobar.com'
>>> email.endswith(blacklisted)
True

你可以在黑名单中同时包含 '.bar.com''@bar.com'。这样做的结果是

>>> blacklisted = ('.bar.com', '@bar.com', '.baz.com', '@baz.com')
>>> email = 'x@foobar.com'
>>> email.endswith(blacklisted)
False

显然,这样会多花一些功夫。到这里我觉得用这种方法和正则表达式相比,主要是个人喜好。虽然我尽量避免使用正则表达式,但对你来说,可能正则表达式更合适。

撰写回答