嘀~正则表达式快速上手指南(下篇)

Posted AI开发者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嘀~正则表达式快速上手指南(下篇)相关的知识,希望对你有一定的参考价值。

本文为「嘀~正则表达式快速上手指南」下篇,阅读上篇请点击:

  以循环方式获取每个名称和地址

接下来我们在电子邮件的 contents 列表中工作。

嘀~正则表达式快速上手指南(下篇)

这个过程总共有 3 步,首先是找到 From: 字段

嘀~正则表达式快速上手指南(下篇)

第一步,我们通过 re.search() 函数找到完整的 From: 字段。 句点 . 表示除了\n之外的任何字符 ,* 延伸到该行的结尾处。然后将它赋给变量 sender.

但是,数据并不总是直截了当的。常常会有意想不到的情况出现。例如,如果没有 From: 字段怎么办?脚本将报错并中断。在步骤2中可以避免这种情况。

嘀~正则表达式快速上手指南(下篇)

为了避免由 From:  域导致的错误,我们要用一个 if 来检查 sender 是不是 None。如果是一个空字段的话,用 s_email 和 s_name 的值来取代 None ,这样脚本就可以继续运行而不是意外中断。

虽然这个教程让使用正则表达式看起来很简单(Pandas在下面)但是也要求你有一定实际经验。例如,我们知道使用if-else语句来检查数据是否存在。事实上,之所以我们知道如何处理,是因为我们在写这个脚本时反复地尝试过。编写代码是一个迭代过程。值得注意的是,即使教程看起来是线性的,即使教程看起来是直截了当的,但实践中需要更多的尝试。

我们用不同的规则来命名,每一个名字的左边都用 "From:" 字段中的:来分割,电子邮件的右边用开括号 <。因此可以用 :.*< 形式来找邮件名称。 我们从每个结果中快速的去掉 : 和 <

现在,让我们打印出代码的结果来看看。

嘀~正则表达式快速上手指南(下篇)

注意我们没有使用 sender 变量在 re.search()函数中作为搜索字符串。我们已经打印了 sender 和 sender.group() 的类型,这样就能看到区别。看起来 sender 是一个 re 的匹配对象,并且不能用re.search()来搜索。然而sender.group() 是一个字符串,而 re.search 接受的参数即是字符串形式。

我们来看看 s_email 和 s_name 长什么样子。

嘀~正则表达式快速上手指南(下篇)

同样,我们得到了匹配的对象。每次对字符串进行re.search() 操作, 都会生成匹配对象, 我们必须将其转换为字符串对象。

在转换之前,回想一下如果没有From: 字段,,sender 的值将会是None,那么 s_email和s_name 的值也将为None。因此,我们必须再次进行检查,以便脚本不会意外中断。先看看如何针对s_email 构造代码。

嘀~正则表达式快速上手指南(下篇)

在步骤3A中,我们使用了if 语句来检查s_email的值是否为 None, 否则将抛出错误并中断脚本。

然后,我们只需将s_email 匹配的对象转换为字符串并将其分配给变量sender_email 即可。将转换完的字符串添加到  emails_dict 字典中,以便后续能极其方便地转换为pandas数据结构。

在步骤3B中,我们对 s_name 进行几乎一致的操作.

嘀~正则表达式快速上手指南(下篇)

就像之前做的一样,我们在步骤3B中首先检查s_name 的值是否为None 。

然后,在将字符串分配给变量前,我们调用两次了 re 模块中的re.sub() 函数。首先,通过用空字符“”代替:\s* ,删除冒号及冒号与姓名之间的任何空格字符。然后删除姓名另一侧的空格字符和角括号,再次使用空字符进行替换。最终,将字符串分配给 sender_name并添加到字典中。

让我们检查下结果。

嘀~正则表达式快速上手指南(下篇)

首先,我们找到To: 字段。

嘀~正则表达式快速上手指南(下篇)

接下来,我们将先发制人,避免recipient 为None的情况发生。

嘀~正则表达式快速上手指南(下篇)

然后我们将匹配对象转换为字符串并添加至字典中去。

嘀~正则表达式快速上手指南(下篇)

因为From: 和 To: 字段具有相同的结构,因此我们可以对两者使用相同的代码,但对其他字段来说,我们需要定制稍微不同的代码。

  获取邮件的日期

现在让我们来获取邮件的发送日期。

嘀~正则表达式快速上手指南(下篇)

我们获取的Date:字段的代码与From:及To:字段的代码相同。就像保证这两个字段的值不是None一样,我们同样要检查被赋值到变量date_field的值是否为 None。

嘀~正则表达式快速上手指南(下篇)

日期是以数字开始的,因此我们可以用 \d 来解析它,就像日期格式中具体天数部分一样,它可能是由一位或者两位数字组成,所以在此+ 就变得非常重要了。在正则表达式里, 在+ 的左侧来匹配一个或多个模式实例。用\d+ 来匹配可以不用考虑日期的具体天数是一位还是两位数字。

之后的一个空格可以通过寻找空白字符的 \s 来解析。月份是由三个字母组成的,因此使用\w+ 来解析,再接另一个空格,所以继续用 \s 解析。因为年份是由多个数字组成,所以我们需要再用一次\d+ 。

表达式 \d+\s\w+\s\d+之所以能起作用,是因为精确的模式匹配约束着空格之间的内容。

接下来,我们做和之前相同的 None 值检查。

嘀~正则表达式快速上手指南(下篇)

如果 date 不为 None ,我们就把它从这个匹配对象转换成一个字符串,然后赋值给变量 date_sent,再将其键值添加到字典中。

进行下一步前,我们应特别注意的是+ 和 * 看起来很相似,但是它们差异很大。用日期字符串来举例:

嘀~正则表达式快速上手指南(下篇)

如果使用 * 我们将匹配到大于等于零个的结果,而 + 匹配大于等于一个的结果。参照以上示例,我们输出了两种不同的结果,它们之间存在非常大的差异。正如所见, + 可以解析出整个日期而*只解析出一个空格和数字1。

接下来讲解邮件的标题。

  获得邮件的标题

我们可以像之前一样,用相同的代码架构来获取我们需要的信息。

嘀~正则表达式快速上手指南(下篇)

现在我们对正则表达式的格式已经很熟悉了对吧?这个代码与之前的类似,为获得标题,我们可以用一个空的字符串来代替"Subject: " 。

  获取邮件的内容

最后要添加到字典里的一项就是邮件的内容了。

嘀~正则表达式快速上手指南(下篇)

将标题从邮件内容中分离出来是非常复杂的任务,尤其当文中有很多不同形式的标题。在原始混乱的数据中是很难找到一致性的规律,但是幸运的是这个工作有人帮我们解决了——Python的email 模块包非常适用这项任务。

我们之前已经导入了email模块. 现在,我们将 message_from_string()方法应用于item, 将整个email转换成 email消息对象. 一个消息对象由消息头和消息体组成, 分别对应于email的头部和主体.

接下来, 我们对email消息对象使用 get_payload()方法. 提取email内容. 并将内容传递给变量 body, 稍后我们会将其存储在字典 emails_dict 的键 "email_body"下.

在处理邮件正文时为什么选择email包而非正则表达式

你可能会疑惑, 为什么使用 email 包而不是正则表达式呢? 因为在不需要大量的清理工作时,正则表达式并不是最好的方法。我们需要为这段代码做详细解释。

我们值得探讨为何会作出这个选择。但在开始之前,我们需要先理解方括号[ ] 在正则表达式中的含义,   .

[ ] 用于匹配所有被它括起来的内容. 比如, 如果需要在字符串中查找 "a", "b", 或 "c" , 可以使用 [abc] 作为模式. 上文提到过的模式也适用。[\w\s] 用于查找字母、数字或空格。不同之处在于,它匹配的是方括号中的文字部分。

现在,可以更好的理解我们为何会决定选择email模块了。

仔细留意下数据就会发现email头部采用字符串 "Status: 0" 或 "Status: R0"作为结束,并在下一封邮件的 From r 字符串前结束,我们可以使用 Status:\s*\w*\n*[\s\S]*From\sr* 来获取email内容. [\s\S]* 用来查找空格或非空格字符,所以用于大段的文本、数字,以及标点符号。

不幸的是一封 email 不止一个“Status: ” 字符串,也并不一定都包含 "From r",即邮件拆分之后的数目可能会比邮件列表的字典数目多 也可能会比它少 ,但它们不会和已有的其他类别相匹配。如果使用 pandas 包来解决这个问题的话 会遇到问题 ,因此,我们选择使用 email 包。

  创建字典列表

最后,添加字典emails_dict到 emails 列表:

嘀~正则表达式快速上手指南(下篇)

此时可以打印emails列表。执行 print(len(emails_dict)) 函数,查看列表中有多少字典和email 。如前述,全部语料库包含 3977个email。我们的小型测试文件中只有7个。全部代码如下:

嘀~正则表达式快速上手指南(下篇)

我们已经打印出了emails 列表的第一项, 它是由键和键值对组成的字典. 由于使用了 for 循环,因此每个字典拥有相同的键,但键值不同。

我们为每个 item 赋值 "email content here" ,所以不需要打印所有的email来占据电脑屏幕. 如果你在家应用时打印email,你将会看到实际的email内容。

  使用 pandas 处理数据

如果使用 pandas 库处理列表中的字典 那将非常简单。每个键会变成列名, 而键值变成行的内容。

我们需要做的就是使用如下代码:

嘀~正则表达式快速上手指南(下篇)

通过上面这行代码,使用pandas的DataFrame() 函数,我们将字典组成的 emails 转换成数据帧,并赋给变量emails_df.

就这么简单。我们已经拥有了一个精致的Pandas数据帧,实际上它是一个简洁的表格,包含了从email中提取的所有信息。

请看下数据帧的前几行:

嘀~正则表达式快速上手指南(下篇)

The dataframe.head() 函数显示了数据序列的前几行。该函数接受1个参数。一个可选的参数用于定义需要显示的行数, n=3 表示前3行。

也可以精确地查找。例如,查找从特定域名发来的邮件。但是,我们需要先学习一种新的正则表达式来完成精确查询工作。

管道符号, |, 用于查找位于它两边的任意字符。 如, a|b查找 a 或 b。

| 有点类似 [ ], 但二者有区别。假设我们需要查找"crab", "lobster", 或 "isopod"。 使用 crab|lobster|isopod 会比 [crablobsterisopod] 更精确,前者会匹配完整单词,而后者只匹配单个字符。

现在我们可以使用 | 符号查找从特定域名发送来的email。

嘀~正则表达式快速上手指南(下篇)

这里我们使用了一行超长的代码。由内及外剖析它。

emails_df['sender_email'] 选择了标记为 sender_email的列,接下来,如果在该列中匹配到 子字符串 "maktoob" 或 "spinfinder" ,则str.contains(maktoob|spinfinder) 返回 True . 最后, 最外面的emails_df[] 返回 sender_email 列视图,该列包含需要匹配的目标字符串。干的漂亮!

我们也可以单个检视邮件。 只需要以下4步。 第1步,查找包含字符串"@maktoob"的列 "sender_email" 对应的行索引。请留意我们是如何使用正则表达式来完成这项任务的。

嘀~正则表达式快速上手指南(下篇)

嘀~正则表达式快速上手指南(下篇)

嘀~正则表达式快速上手指南(下篇)

第4步将展示提取到的email正文

嘀~正则表达式快速上手指南(下篇)

在第四步中 emails_df['sender_email'] == "james_ngola2002@maktoob.com"  是用来查找包含 "james_ngola2002@maktoob.com" 的邮件发送者列,接下来  ['email_body'].values 用来查找邮件正文的相同行的列值,最后输出该列值。

如你所见,我们可以多种方式应用正则表达式,正则表达式也能与pandas完美配合。

  其他资源

自从应用范围从生物学扩展到工程领域,过去这些年正则表达式发展速度惊人 。今天,正则表达式已可在多种变成语言中应用,除基本模式外,有适当变化。在这份教程中,我们使用Python练习使用正则表达式,但如果你喜欢,也可以使用 Stack Overflow 发掘它的其他特点。维基百科用一张表格比较了不同正则表达式引擎的特点。

正则表达式还有很多特性本教程不能一一列举,完整的文档可以参考Python文档中的 re 模块. 谷歌也有一份快速参考手册(https://developers.google.com/edu/python/regular-expressions)

如果需要一系列数据进行实验的话, Kaggle 和 StatsModels 将对你有所帮助。

这里是正则表达式的速查表,但对大多数来说也是有帮助的。

如果这篇教程对你有用的话,你也会喜欢 Dataquest 的正则表达式课程

原文链接:https://www.dataquest.io/blog/regular-expressions-data-scientists/嘀~正则表达式快速上手指南(下篇)

4 月 AI 求职季

8 大明星企业

10 场分享盛宴

20 小时独门秘籍

4.10-4.19,我们准时相约!



新人福利



关注 AI 研习社(okweiwu),回复  1  领取

【超过 1000G 神经网络 / AI / 大数据资料】



嘀~正则表达式快速上手指南(上篇)

以上是关于嘀~正则表达式快速上手指南(下篇)的主要内容,如果未能解决你的问题,请参考以下文章

快速学习正则表达式,不用死记硬背,示例让你通透(下篇)

理清JavaScript正则表达式--下篇

爬虫必学知识之正则表达式下篇

iOS小技能:NSPredicate在正则表达式的应用下篇

数字IC验证进阶以一个实例,快速上手python脚本处理log的若干关键操作(#python#正则表达式)

数字IC验证进阶以一个实例,快速上手python脚本处理log的若干关键操作(#python#正则表达式)