[英]Ignore strings which do not completely match regex?
我想使用正则表达式返回电子邮件的所有收件人。 例如:
Date: Wed, 6 Dec 2000 02:03:00 -0800 (PST)
From: donald.herrick@enron.com
To: brianherrick@email.msn.com, herriceu2@tdprs.state.tx.us,
robertherrick@bankunited.com, kristi.demaiolo@enron.com,
suresh.raghavan@enron.com, harry.arora@enron.com
Subject: FW: If Santa Answered his mail...
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-From: Donald W Herrick
X-To: brianherrick@email.msn.com, HERRICEU2@tdprs.state.tx.us, RobertHerrick@bankunited.com, Kristi Demaiolo, Suresh Raghavan, Harry Arora
X-cc:
X-bcc:
应该返回(从“收件人:”行) brianherrick @ email.msn.com,herriceu2 @ tdprs.state.tx.us,robertherrick @ bankunited.com,kristi.demaiolo @ enron.com,suresh.raghavan @ enron.com ,harry.arora @ enron.com
但不是 (来自“ X-To:”行) brianherrick @ email.msn.com,HERRICEU2 @ tdprs.state.tx.us,RobertHerrick @ bankunited.com 。
我当前的正则表达式是re.findall([To:\\s][\\w\\.-]+@[\\w\\.-]+, text)
,它返回“ To:”,“ X-To:”中的所有内容和“发件人:”行。
我的问题:
[To:\\s]
部分不匹配? 作为@MartijnPieters答案的附录,正则表达式可能不是JOB的正确工具。 要解析电子邮件,建议使用email.parser
>>> from email.parser import Parser
>>> headers = Parser().parsestr(email_str)
>>> pprint.pprint(map(str.strip, headers['to'].split()))
['brianherrick@email.msn.com,',
'herriceu2@tdprs.state.tx.us,',
'robertherrick@bankunited.com,',
'kristi.demaiolo@enron.com,',
'suresh.raghavan@enron.com,',
'harry.arora@enron.com']
您误解了角色类的作用; 您随时随地模式相匹配的字符串包含一个T
, o
, :
或空白字符。
这是因为[To:\\s]
一个字符类建模,集合中的任何一个字符都将匹配。 这就是为什么您的From:
行匹配; :
和d
之间的空格在这里就足够了。
如果您需要验证整个标题名称,请使用^
将匹配项锚定到行的开头,但删除该字符类:
r'^To:\s+[\w\.-]+@[\w\.-]+'
现在,如果使用re.MULTILINE
标志,则To:
部分仅在行的开头才匹配:
>>> import re
>>> text = '''\
... Date: Wed, 6 Dec 2000 02:03:00 -0800 (PST)
... From: donald.herrick@enron.com
... To: brianherrick@email.msn.com, herriceu2@tdprs.state.tx.us,
... robertherrick@bankunited.com, kristi.demaiolo@enron.com,
... suresh.raghavan@enron.com, harry.arora@enron.com
... Subject: FW: If Santa Answered his mail...
... Mime-Version: 1.0
... Content-Type: text/plain; charset=us-ascii
... Content-Transfer-Encoding: 7bit
... X-From: Donald W Herrick
... X-To: brianherrick@email.msn.com, HERRICEU2@tdprs.state.tx.us, RobertHerrick@bankunited.com, Kristi Demaiolo, Suresh Raghavan, Harry Arora
... X-cc:
... X-bcc:
... '''
>>> re.findall(r'^To:\s+[\w\.-]+@[\w\.-]+', text)
[]
>>> re.findall(r'^To:\s+[\w\.-]+@[\w\.-]+', text, flags=re.M)
['To: brianherrick@email.msn.com']
这只能匹配第一个电子邮件地址,并且不包含全名(例如Brian Herrick <brianherrick@email.msn.com>
)。
您必须匹配整个标题 :
re.findall(r'^To:\s+((?:.*(?:\n[ \t]+)?)*)', text, flags=re.M)
这与To:
头匹配,后跟任意数量的头连续行(以空格开头):
>>> re.findall(r'^To:\s+((?:.*(?:\n[ \t]+)?)*)', text, flags=re.M)
['brianherrick@email.msn.com, herriceu2@tdprs.state.tx.us, \n robertherrick@bankunited.com, kristi.demaiolo@enron.com, \n suresh.raghavan@enron.com, harry.arora@enron.com']
并且您必须分别提取电子邮件地址。
就我个人而言,我将研究email
包 ,这将使抓取标头变得更加容易:
import email
message = email.message_from_string(text)
to_headers = message.get_all('to')
addresses = email.utils.getaddresses(to_headers)
演示:
>>> import email
>>> m = email.message_from_string(text)
>>> m.get_all('to')
['brianherrick@email.msn.com, herriceu2@tdprs.state.tx.us, \n robertherrick@bankunited.com, kristi.demaiolo@enron.com, \n suresh.raghavan@enron.com, harry.arora@enron.com']
>>> email.utils.getaddresses(m.get_all('to'))
[('', 'brianherrick@email.msn.com'), ('', 'herriceu2@tdprs.state.tx.us'), ('', 'robertherrick@bankunited.com'), ('', 'kristi.demaiolo@enron.com'), ('', 'suresh.raghavan@enron.com'), ('', 'harry.arora@enron.com')]
现在,您拥有了所有的电子邮件地址。
当使用正则表达式时,也可以应用email.utils.getaddresses()
函数 :
>>> email.utils.getaddresses(re.findall(r'^To:\s+((?:.*(?:\n[ \t]+)?)*)', text, flags=re.M))
[('', 'brianherrick@email.msn.com'), ('', 'herriceu2@tdprs.state.tx.us'), ('', 'robertherrick@bankunited.com'), ('', 'kristi.demaiolo@enron.com'), ('', 'suresh.raghavan@enron.com'), ('', 'harry.arora@enron.com')]
regex
模块:无限向后看及其他功能
如果要使用正则表达式,建议您使用出色的regex
模块,而不要使用re
。 此正则表达式将返回所有匹配项:
(?<=(?<!X\S+)To:\s*(?:[^@\s]+@[^\,\s]+,\s*)*?)[^@\s]+@[^\,\s]+
样例代码
我在Python 3.4中对此进行了测试。
import regex
subject = """Date: Wed, 6 Dec 2000 02:03:00 -0800 (PST)
From: donald.herrick@enron.com
To: brianherrick@email.msn.com, herriceu2@tdprs.state.tx.us,
robertherrick@bankunited.com, kristi.demaiolo@enron.com,
suresh.raghavan@enron.com, harry.arora@enron.com
Subject: FW: If Santa Answered his mail...
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-From: Donald W Herrick
X-To: brianherrick@email.msn.com, HERRICEU2@tdprs.state.tx.us, RobertHerrick@bankunited.com, Kristi Demaiolo, Suresh Raghavan, Harry Arora
X-cc:
X-bcc: """
pattern = "(?<=(?<!X\S+)To:\s*(?:[^@\s]+@[^\,\s]+,\s*)*?)[^@\s]+@[^\,\s]+"
for match in regex.finditer(pattern, subject):
print(match.group())
产量
brianherrick@email.msn.com
herriceu2@tdprs.state.tx.us
robertherrick@bankunited.com
kristi.demaiolo@enron.com
suresh.raghavan@enron.com
harry.arora@enron.com
说明
[^@\\s]+@[^\\,\\s]+
,它匹配不是arrobas或空白字符的任何字符,然后是arrobas,然后是不是逗号或空格字符(输入中的电子邮件结尾定界符) (?<!X-)To:\\s*
与To:
匹配,只要不以Xsomething
,就由否定的后向(?<!X-)
断言 (?:[^@\\s]+@[^\\,\\s]+,\\s*)*?
匹配表达式[^@\\s]+@[^\\,\\s]+,\\s*
所需的数量( *?
)以允许后面的匹配。 这是一个“电子邮件跳过程序”,我们可以在每次匹配时逐渐跳过越来越多的电子邮件 [^@\\s]+@[^\\,\\s]+,\\s*
只是简单的电子邮件,后跟一个逗号和可选的空格字符( \\s
不仅匹配空格,而且还匹配回车符,制表符等。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.