我可以从电子邮件中提取信息列表吗?

时间:2019-03-05 00:43:41

标签: zapier

我每天都会收到一封电子邮件,其中列出了即将到来的约会及其时长。约会的数量每天都有所不同。

电子邮件如下:

================

今天的时间表

9:30 AM

3h

巴西的井喷

[客户#1名称]

12:30 PM

1h

女性剪裁

[客户端2名称]

6:00 PM

45m

男人的削减

[客户#3名称]

预计收入

==================

我想为每个约会在Google日历中创建一个事件,看来zapier MIGHT可以执行此操作,但是我能找到的所有帮助资源本质上都是非常通用的。

这在Zapier上可行吗?如果是这样,那么朝着正确方向前进的任何微调都是很棒的。

任何想法都值得赞赏。

1 个答案:

答案 0 :(得分:2)

我有一段时间杀死并享受奇怪的挑战。因此,我整理了一个解决方案,该解决方案应该可以满足您的需求。我将按步骤进行分解。

模板


Zapier触发器-步骤1
类型:触发器
模块:Gmail
条件:取决于用户
注释:对于触发器zap,您将要使用Gmail特定的触发器,如果​​在收件箱中设置了过滤器,则效果类似于“对标题为'xyz'的电子邮件执行触发器”或“标有'xyz'的电子邮件”。 br />

输入屏幕截图:enter image description here

输出屏幕截图:enter image description here

Zapier动作-步骤2
类型:动作
模块:代码(Python 3)
注释:Zapier提供的代码执行您放置在其容器中的任何(正确编写的)代码。它特别方便,因为它允许您通过使用名为“ input_data”的字典变量将先前步骤中的数据并入其中。 Zapier提供两种语言的Code模块:Javascript和Python。因为我最熟悉Python,所以此步骤的解决方案是用Python编写的。我会将代码附加到此答案的末尾。使用电子邮件正文中保存的数据(在步骤1中检索到),我们可以执行一些字符串操作和日期时间转换,以将电子邮件分解为各个组成部分,然后将其传递给以下操作步骤:创建日历事件。

输入屏幕截图:enter image description here

输出屏幕截图:enter image description here

Zapier操作-步骤3
类型:动作
模块:Google日历-创建事件
注释:使用上一个代码步骤输出的数据,我们可以填写用于创建新约会的必填字段。

输入屏幕截图:enter image description here 输出屏幕截图:enter image description here

PYTHON代码


from datetime import timedelta, date, datetime
''' 
Goal: Extract individual appointment details from variable length email
Steps:
  Remove all extraneous and new line characters.
  Isolate each individual appointment and group its relevant details.
  Derive appointment start and end times using appointment time and duration.
  Return all appointments in a list.
'''

def format_appt_times(appt_dict):

  appt_start_str = appt_dict.get("appt_start")
  appt_dur_str = appt_dict.get("appt_length") 

  # isolate hour and minutes from appointment time
  appt_s_hour = int(appt_start_str[:appt_start_str.find(":")])
  if ("pm" in appt_start_str.lower()):
      appt_s_hour = 12 if appt_s_hour + 12 >= 24 else appt_s_hour + 12 

  appt_s_min = int(appt_start_str[appt_start_str.find(":") + 1 :
                                  appt_start_str.find(":") + 3])

  # isolate hour and minutes from duration time
  appt_d_hour = 0
  appt_d_min = 0
  if ("h" in appt_dur_str):
      appt_d_hour = int(appt_dur_str[:appt_dur_str.find("h")])
  if ("m" in appt_dur_str):
      appt_d_min = int(appt_dur_str[appt_dur_str.find("m") - 2 : appt_dur_str.find("m")])

  # NOTE: adjust timedelta hours depending on your relation to UTC
  # create datetime objects for appointment start and end times
  time_zone = timedelta(hours=0)
  tdy = date.today() - time_zone
  duration = timedelta(hours=appt_d_hour, minutes=appt_d_min)
  appt_start_dto = datetime(year=tdy.year,
                          month=tdy.month,
                          day=tdy.day,
                          hour=appt_s_hour,
                          minute=appt_s_min)
  appt_end_dto = appt_start_dto + duration

  # return properly formatted datetime as string for use in next step.
  return (appt_start_dto.strftime("%Y-%m-%dT%H:%M"),
        appt_end_dto.strftime("%Y-%m-%dT%H:%M"))

def partition_list(target, part_size):

  for data in range(0, len(target), part_size):
      yield target[data : data + part_size]

def main():

  # Remove all extraneous and new line characters.
  email_body = input_data.get("email_body")
  head,delin,*email_body,delin,foot = [text for text in email_body.splitlines() if text != ""]

  appointment_list = []
  # Isolate each individual appointment and group its relevant details.

  for text in partition_list(email_body, 4):
      template = {
          "appt_start" : text[0],
          "appt_end" : None,
          "appt_length" : text[1],
          "appt_title" : text[2],
          "appt_client" : text[3]
          }
      appointment_list.append(template)

  for appt in appointment_list:
      appt["appt_start"], appt["appt_end"] = format_appt_times(appt)

  return appointment_list

return main()

我不确定您是否熟悉Python或更一般的编程,但是代码中的注释解释了每个部分的工作。如果您对代码方面有任何特定疑问,请告诉我。假设您的电子邮件模板没有更改,则此设置应完全按需要工作。让我知道是否有任何不清楚的地方。

更新


我认为,如果其他人有类似的问题,最好在原始答案中回答您的问题。

解释此代码如何删除多余的字符:

第一行实际上有很多事情要做,所以我会尽力分解它,并在必要时提供资源。

相关代码:

  head,delin,*email_body,delin,foot = [text for text in email_body.splitlines() if text != ""]

这里的第一步是将文本分成可管理的块。我是使用email_body.splitlines()行来实现的,默认情况下,该行将在找到的每个换行符处将字符串分成列表(您可以指定自己的定界符)。

如果我们现在要检查列表,则其内容可能是以下内容:

["================", "", "Today's Schedule", "", "9:30 AM", "", "3h", ..., "[Client #3 name]", "", "Projected Revenue", "", "==================="]

您会发现其中确实有很多我们真正不想要的信息。

首先让我们看一下“”元素。由于每行文本之间有空白行,因此保留了这些行,即使这些行是空白的,它们的末尾仍然会有换行符。您可以通过多种方式在python中解决此问题。我们可以简单地编写一个for循环来遍历并将所有非“”元素复制到新列表中。

对我来说,这感觉像是额外的工作,此外,Python还在这种情况下提供了列表理解功能。我不会深入了解列表理解,因为有很多可以说的,而且比我可以用的见解更多,但是它实质上允许您针对一组“数据”提供逻辑以形成一个列表。清单。在这种情况下,我特别想过滤掉从splitlines()调用返回的“”元素。

因此,您将看到我在下面的行中进行处理

[text for text in email_body.splitlines() if text != ""]

有了这个,我们上面有了一个列表,减去了“”元素。现在,我们必须将注意力转向更具“动态性”的垃圾字符串。同样,有很多方法可以做到这一点。一种选择(不是特别灵活)可以是简单地将要删除的字符串存储在变量中,以达到以下目的:

garb_1 = "==================="
garb_2 = "Projected Revenue"
garb_3 = ...

并再次使用另一个for循环过滤列表。相反,我选择利用Python的列表解包习惯。这使我们能够将列表对象(我相信元组)“解包”为变量。例如:

one, two, three = ["a", "b", "c"]

我敢肯定,只要我们提供与列表中相同数量的变量,就可以猜出上面发生了什么,我们可以以此方式“解压缩”它。可是等等!在我们的情况下,我们不知道列表会持续多久,因为它完全取决于您在任何一天的约会次数。好吧,这是星形拆包进入提升功能的地方。以我的代码为例:

head,delin,*email_body,delin,foot = [text for text in email_body.splitlines() if text != ""]

*用简单的英文*表示“我不知道要列出列表中的全部元素是多少”。我们知道,在电子邮件的开头和结尾始终会出现两行垃圾,我们可以使用可变长度* email_body容器分配它们以丢弃变量并捕获之间的所有内容。

完成所有这些操作后,我们现在有了一个列表,其中仅包含我们要捕获的数据。如您所说,如果在email_body之前或之后还有其他垃圾行,则可以简单地添加其他丢弃变量来解决它们。

再一次询问任何后续问题。

迈克尔

资源


List Comprehension
Star Unpacking