@infirmitive

Как распарсить письмо при помощи bs4?

Здравствуйте! Хочу достать из письма код для 2фа.

from itertools import chain
from bs4 import BeautifulSoup
import time
import imaplib
import email
import email.message

username, password = input('Введи логин;пароль: ').split(';')

criteria = {
    'FROM':    'help@acct.epicgames.com',
    'SUBJECT': 'Ваш код двухфакторной аутентификации',
}
uid_max = 0


def search_string(uid_max, criteria):
    c = list(map(lambda t: (t[0], '"'+str(t[1])+'"'),
                 criteria.items())) + [('UID', '%d:*' % (uid_max+1))]
    return '(%s)' % ' '.join(chain(*c))


def get_first_text_block(msg):
    type = msg.get_content_maintype()

    if type == 'multipart':
        for part in msg.get_payload():
            if part.get_content_maintype() == 'text':
                return part.get_payload()
    elif type == 'text':
        return msg.get_payload()


server = imaplib.IMAP4_SSL('mail.example.com')
server.login(username, password)
server.select('INBOX')
print('Успешно подключились к ' + username)
result, data = server.uid('search', None, search_string(
    uid_max, criteria).encode('utf-8'))

uids = [int(s) for s in data[0].split()]
if uids:
    uid_max = max(uids)

server.logout()

while 1:
    server = imaplib.IMAP4_SSL('mail.example.com')
    server.login(username, password)
    server.select('INBOX')

    result, data = server.uid('search', None, search_string(
        uid_max, criteria).encode('utf-8'))

    uids = [int(s) for s in data[0].split()]
    for uid in uids:
        if uid > uid_max:
            result, data = server.uid(
                'fetch', str(uid), '(RFC822)')
            msg = email.message_from_bytes(data[0][1])

            uid_max = uid

            text = get_first_text_block(msg)
            soup = BeautifulSoup(text, 'lxml')
            code = soup.find(
                'div', style='font-family: arial,helvetica,sans-serif; mso-line-height-rule: exactly; color: #313131; text-align: center; font-size: 40px; letter-spacing: 15x; line-height: 100px')
            print(code.text)

    server.logout()
time.sleep(1)

При получении письма BS никак не хочет распарсить html код (или я что-то не так написал).
Принт переменной soup успешно выводит тело письма в html, а вот найти div по указанному style и вывести его текст не получается.
Пишет NoneType в print(code.text)

Сам html выглядит вот так:
<div style="font-family: arial,helvetica,sans-serif; mso-line-height-rule: exactly; color: #313131; text-align: center; font-size: 40px; letter-spacing: 15px; line-height: 100px">
366634
</div>
  • Вопрос задан
  • 150 просмотров
Решения вопроса 1
hottabxp
@hottabxp Куратор тега Python
Сначала мы жили бедно, а потом нас обокрали..
Нужно искать по атрибуту:
code = soup.find('div',attrs={'style':'font-family: arial,helvetica,sans-serif; mso-line-height-rule: exactly; color: #313131; text-align: center; font-size: 40px; letter-spacing: 15px; line-height: 100px'}).text.strip()
	print(code)
	>>> 366634
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@TheAngryPython
С использованием регулярных выражений
import re
pattern = re.compile('[^#][<>\n](\d\d\d\d\d\d)[<>\n]')
pattern.findall('<div style="font-family: arial,helvetica,sans-serif; mso-line-height-rule: exactly; color: #313131; text-align: center; font-size: 40px; letter-spacing: 15px; line-height: 100px">366634</div>')
['366634']
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы