繁体   English   中英

由于“\r\n”,无法正确解析来自 Gmail 的电子邮件

[英]Failing to parse email from Gmail correcty because of `\r\n`

我在 Gmail 中有一封简单的电子邮件,如下所示:

Hi all

@alice - please prepare XXX for tomorrow
@bob - please prepare YYY for tomorrow

best,
Z

我想获取它,解析它并用换行符分割,所以我会得到一个包含 5 个元素的列表:

['Hi all','@alice ...', '@bob ...', 'best,','Z']

但由于某些原因在句子中我得到\r\n这让我将行分成 2 行,尽管在原始电子邮件中没有新行。

我将其解析如下(在获得正确的凭据后)

txt = service.users().messages().get(userId=user.email, id=email_msg['id']).execute()
payload = txt["payload"]
headers = payload["headers"]

parts = payload.get("parts")[0]
data = parts["body"]["data"]
data = data.replace("-", "+").replace("_", "/")
decoded_message = str(base64.b64decode(data), "utf-8")
split = decoded_message.splitlines()
final_split = list(filter(None, split))

但随后我收到的消息如下所示:

Hi all\r\n\r\n@alice - please prepare XXX\r\nfor tomorrow\r\n@bob - please prepare YYY for tomorrow\\r\nr\nbest,\n\rZ

所以如果我按\r\n\n拆分,我会得到无效的结果

当您使用b64decode()解码数据时,您不会得到字符串,而是会得到一个字节字符串。 这是对差异的一个很好的解释。 在尝试解析消息之前,您必须将其转换为常规字符串。

您可以通过运行.decode("utf-8")来做到这一点。 然后你可以使用.splitlines()来分割消息。

txt = service.users().messages().get(userId=user.email, id=email_msg['id']).execute()
payload = txt["payload"]
headers = payload["headers"]

parts = payload.get("parts")[0]
data = parts["body"]["data"]
data = data.replace("-", "+").replace("_", "/")
decoded_data = base64.b64decode(data)

decoded_message = decoded_data.decode("utf-8") # decodes the byte string

split = decode_message.splitlines() # splits the message into a list

final_split = list(filter(None, split)) # this removes the blank lines

在消息上运行.decode()将改变它:

Hi all\r\n\r\n@alice - please prepare XXX\r\nfor tomorrow\r\n@bob - please prepare YYY for tomorrow\\r\nr\nbest,\n\rZ

到原始消息:

Hi all

@alice - please prepare XXX for tomorrow
@bob - please prepare YYY for tomorrow

best,
Z

然后在.splitlines()之后你会得到这个列表:

['Hi all', '', '@alice...', '@bob...', '', 'best,', 'Z']

请注意,有对应于空白行的空白字符串。 要摆脱它们,您可以运行最后一行final_split = list(filter(None, split)) ,这将为您提供所需的内容。 还有其他方法

['Hi all', '@alice...', '@bob...', 'best,', 'Z']

顺便说一句,我没有为此安装BeautifulSoup ,但如果你想使用它,你可能想在解码字节字符串后添加它。

正如 Daniel 在评论中所建议的,我使用 HTML 数据来正确提取消息:

我定义了HTML解析器:

from html.parser import HTMLParser
from io import StringIO

def extract_text(html_text: str) -> str:
    class MLStripper(HTMLParser):
        def __init__(self):
            super().__init__()
            self.reset()
            self.strict = False
            self.convert_charrefs = True
            self.text = StringIO()

        def handle_data(self, d):
            self.text.write(d)

        def get_data(self):
            return self.text.getvalue()

    def strip_tags(html):
        s = MLStripper()
        s.feed(html)
        return s.get_data()

    cleaned_html_text = html_text.replace('</div>', '\n</div>').replace('\r\n', '')\
        .replace('<br>', '\n').replace('\xa0', ' ')
    return strip_tags(cleaned_html_text)```

然后在HTML上运行它:

parts = payload.get("parts")[1] # take the HTML part
data = parts["body"]["data"]
data = data.replace("-", "+").replace("_", "/")
decoded_message = str(base64.b64decode(data), "utf-8")
extracted_message = extract_text(html_text=decoded_message)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM