Я пытаюсь создать скрипт Python, который может читать данные JSON в электронной почте Outlook. Но проблема заключается в том, как извлечь данные JSON из данных HTML. Это мои исходные данные JSON, которые я хочу извлечь.
{
"vpn_detail":
{
"username":"harnishs",
"tokens":
[
"85188605",
"00422786",
],
"cluster_name":"*******.com"
}
}
Итак, я прочитал эти данные JSON, используя imaplib в Outlook, но он прочитал данные JSON в HTML. Таким образом, эти данные JSON преобразуются в HTML, он читает электронную почту Outlook, как это (в HTML-форме),
b'<html>\r\n<head>\r\n<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Diso-8859-=\r\n1">\r\n<style type=3D"text/css" style=3D"display:none;"><!-- P {margin-top:0;margi=\r\nn-bottom:0;} --></style>\r\n</head>\r\n<body dir=3D"ltr">\r\n<div id=3D"divtagdefaultwrapper" style=3D"font-size:12pt;color:#000000;font=\r\n-family:Calibri,Helvetica,sans-serif;" dir=3D"ltr">\r\n<p style=3D"margin-top:0;margin-bottom:0"></p>\r\n<div>{<br>\r\n"vpn_detail":<br>\r\n {<br>\r\n "username":"kushpate&q=\r\nuot;, <br>\r\n "tokens":  =\r\n;<br>\r\n [<br>\r\n  =\r\n;"85188605",<br>\r\n  =\r\n;"00422786",<br>\r\n  =\r\n;"94548619",<br>\r\n  =\r\n;"51249494",<br>\r\n  =\r\n;"HHEF0EA5",<br>\r\n  =\r\n;"2E09A81E"<br>\r\n ],<br>\r\n "cluster_name":"bgl13-=\r\nvpn-cluster-2.cisco.com"<br>\r\n }<br>\r\n<br>\r\n}</div>\r\n<br>\r\n<p></p>\r\n</div>\r\n</body>\r\n</html>\r\n'
Итак, теперь из этих данных HTML я хочу тот же файл JSON, Я сделал свой код таким,
from bs4 import BeautifulSoup
MyStr = """ HTML data """
soup = BeautifulSoup(MyStr, "html.parser")
print(soup.text.strip().replace(" ", ""))
Итак, этот код дает мне этот результат,
b'
<!--P{margin-top:0;margi=
n-bottom:0;}-->
{
"vpn_detail":
{
"username":"harnishs&q;=
uot;,
"tokens": =
;
[
=
;"85188605",
=
;"00422786",
=
;"94548619",
=
;
],
"cluster_name":"***********.com"
}
}
'
Но я хочу, чтобы эти данные были такими же, как входные данные JSON, тем не менее, это не точный майнинг. Предложите мне какие-либо изменения, чтобы я мог получать те же данные JSON по электронной почте.
И вам нужно указать кодировку, чтобы избавиться от всех тегов &q;=...
Попробуйте re.search(r'{\s*"\w+".*}', soup.text.strip().decode("utf8"), re.S).group()
@WiktorStribiżew ДА, мой вывод улучшился, но я все еще не получаю точных данных JSON. Я хочу удалить эту строку (&q;= uot;,) из имени пользователя. Теперь мой вывод выглядит следующим образом: ``` { "vpn_detail": { "username": "harnishs" = uot;, "токены": = ; [ = ;"85188605", = ;"00422786", = ;"94548619 ", = ;"51249494", = ;"HHEF0EA5", = ;"2E09A81E" ], "имя_кластера":"bgl13-= vpn-cluster-2.cisco.com" } } ```
re.search(r'{\s*"\w+".*}', s.decode("UTF8"), re.S).group().strip().replace('&q;=\nuot;', '"')? Всегда ли есть новая строка после =?
@WiktorStribiżew Нет знака =, я хочу, чтобы данные были такими же, как данные JSON, о которых я упоминал выше. Это мои данные JSON, мне нужны такие же данные. ``` { "vpn_detail": { "username": "harnishs", "tokens": [ "85188605", "00422786", "94548619", "51249494", "HHEF0EA5", "2E09A81E" ], "cluster_name" :"bgl13-vpn-cluster-2.cisco.com" } } ```
Я удалил строку s.decode("UTF8"), потому что она дает мне [AttributeError: у объекта 'str' нет атрибута 'decode'], поэтому она была запущена, но теперь во втором комментарии она дает мне эту ошибку [TypeError: ожидаемая строка или байтовый объект ] @WiktorStribiżew
Вам нужно преобразовать строку байтов в строку UTF8 для работы со строками. Я вижу, у вас есть b'...' в вопросе, поэтому мой .decode("utf8").
Извините, re.sub(r'\s+(?:=\s*;\s*)?', ' ', re.search(r'{\s*"\w+".*}', s.decode("UTF8"), re.S).group().strip()).replace('&q;= uot;','"'), см. ideone.com/ULtkk8
но [ b'...' ] уже удален из-за вашего первого комментария. @ВикторСтрибижев
См. ideone.com/ULtkk8, работает ли он должным образом?
NameError: имя 's' не определено @WiktorStribiżew
@HarnishShah Я использую s в своей демонстрации, используйте твоя переменная, soup.text. re.sub(r'\s+(?:=\s*;\s*)?', ' ', re.search(r'{\s*"\w+".*}', soup.text.decode("UTF8"), re.S).group().strip()).replace('&q;= uot;','"')
@WiktorStribiżew Теперь мой код выглядит как этот суп = BeautifulSoup(MyStr, "html.parser") суп5 = суп.MyStr.re.sub(r'\s+(?:=\s*;\s*)?', ' ', re.search(r'{\s*"\w+".*}', sup.MyStr.decode("UTF8"), re.S).group().strip()).replace('&q ;= uot;','"') print(soup5) теперь получил эту ошибку [AttributeError: объект 'NoneType' не имеет атрибута 're']
Вы не используете мой код. Строка, конечно, не имеет свойства re. Попробуйте этот код: ideone.com/YwmJH3. Он не компилируется онлайн, он должен работать в вашей консоли.
Давайте продолжить обсуждение в чате.






Вы можете значительно упростить свою задачу с помощью библиотеки html2text, которая сделает почти всю работу, вам нужно будет только убрать ненужные знаки препинания и заменить искаженные кавычки настоящими ":
import re, json, html2text
MyStr = b'<html>\r\n<head>\r\n<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Diso-8859-=\r\n1">\r\n<style type=3D"text/css" style=3D"display:none;"><!-- P {margin-top:0;margi=\r\nn-bottom:0;} --></style>\r\n</head>\r\n<body dir=3D"ltr">\r\n<div id=3D"divtagdefaultwrapper" dir=3D"ltr" style=3D"font-size: 12pt; colo=\r\nr: rgb(0, 0, 0); font-family: Calibri, Helvetica, sans-serif, "EmojiFo=\r\nnt", "Apple Color Emoji", "Segoe UI Emoji", NotoCo=\r\nlorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymb=\r\nols;">\r\n<p style=3D"margin-top:0; margin-bottom:0"></p>\r\n<div>\r\n<div>{<br>\r\n"vpn_detail":<br>\r\n {<br>\r\n "username":"kushpate&q=\r\nuot;, <br>\r\n "tokens":  =\r\n;<br>\r\n [<br>\r\n  =\r\n;"85188605",<br>\r\n  =\r\n;"00422786",<br>\r\n  =\r\n;"94548619",<br>\r\n  =\r\n;"51249494",<br>\r\n  =\r\n;"HHEF0EA5",<br>\r\n  =\r\n;"2E09A81E"<br>\r\n ],<br>\r\n "cluster_name":"bgl13-=\r\nvpn-cluster-2.cisco.com"<br>\r\n }<br>\r\n<br>\r\n}</div>\r\n</div>\r\n<br>\r\n<p></p>\r\n</div>\r\n</body>\r\n</html>\r\n'
MyStrTxt = html2text.html2text(MyStr.decode("utf8"))
clean_string = re.sub(r'(&q;=\s*uot;)|=\s*;\s*', lambda x: '"' if x.group(1) else '', MyStrTxt)
js = json.loads(clean_string)
print(js['vpn_detail']['username'])
# => 'kushpate'
ПРИМЕЧАНИЯ:
MyStr.decode("utf8")html2text.html2text(MyStr.decode("utf8")) очистит HTML от вашей строки, вы сразу получите свой JSONre.sub(r'(&q;=\s*uot;)|=\s*;\s*', lambda x: '"' if x.group(1) else '', MyStrTxt) удаляет все вхождения =; с пробелами между ними, если они есть, или заменяет &q;=+ноль или более пробелов+uot; настоящим " символом.Спасибо за ответ @WiktorStribizew, но я не хочу удалять вручную, потому что каждый раз, когда я читаю электронную почту с помощью python, эти данные JSON будут разными, но формат тот же, поэтому как я могу получить те же данные JSON из данных HTML, это мой вопрос . Ваш код дает мне ответ только [kushate], в то время как мне нужны все данные JSON.
@ХарнишШах print(js). Пожалуйста, поиграйтесь с кодом. Очень легко print() выбрать любую интересующую вас переменную.
да Это работает. Спасибо @Wiktor за лучшее решение.
Ваши шансы значительно увеличатся, если вы отправите данные JSON в виде обычного текстового сообщения электронной почты, а не в формате HTML.