Как извлечь данные JSON из данных HTML с помощью Python?

Я пытаюсь создать скрипт 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&quot;vpn_detail&quot;:<br>\r\n&nbsp;&nbsp; &nbsp;{<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&quot;username&quot;:&quot;kushpate&q=\r\nuot;,&nbsp;&nbsp; &nbsp;<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&quot;tokens&quot;:&nbsp;&nbsp; &nbsp=\r\n;<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;[<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;85188605&quot;,<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;00422786&quot;,<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;94548619&quot;,<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;51249494&quot;,<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;HHEF0EA5&quot;,<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;2E09A81E&quot;<br>\r\n&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;],<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&quot;cluster_name&quot;:&quot;bgl13-=\r\nvpn-cluster-2.cisco.com&quot;<br>\r\n&nbsp;&nbsp; &nbsp;}<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 по электронной почте.

Ваши шансы значительно увеличатся, если вы отправите данные JSON в виде обычного текстового сообщения электронной почты, а не в формате HTML.

Robby Cornelissen 25.06.2019 10:37

И вам нужно указать кодировку, чтобы избавиться от всех тегов &q;=...

creyD 25.06.2019 10:38

Попробуйте re.search(r'{\s*"\w+".*}', soup.text.strip().decode("utf8"), re.S).group()

Wiktor Stribiżew 25.06.2019 11:45

@WiktorStribiżew ДА, мой вывод улучшился, но я все еще не получаю точных данных JSON. Я хочу удалить эту строку (&q;= uot;,) из имени пользователя. Теперь мой вывод выглядит следующим образом: ``` { "vpn_detail": { "username": "harnishs" = uot;, "токены": = ; [ = ;"85188605", = ;"00422786", = ;"94548619 ", = ;"51249494", = ;"HHEF0EA5", = ;"2E09A81E" ], "имя_кластера":"bgl13-= vpn-cluster-2.cisco.com" } } ```

Harnish Shah 25.06.2019 12:19
re.search(r'{\s*"\w+".*}', s.decode("UTF8"), re.S).group().strip().replace('&q;=\nuot;', '"')? Всегда ли есть новая строка после =?
Wiktor Stribiżew 25.06.2019 12:23

@WiktorStribiżew Нет знака =, я хочу, чтобы данные были такими же, как данные JSON, о которых я упоминал выше. Это мои данные JSON, мне нужны такие же данные. ``` { "vpn_detail": { "username": "harnishs", "tokens": [ "85188605", "00422786", "94548619", "51249494", "HHEF0EA5", "2E09A81E" ], "cluster_name" :"bgl13-vpn-cluster-2.cisco.com" } } ```

Harnish Shah 25.06.2019 12:34

Я удалил строку s.decode("UTF8"), потому что она дает мне [AttributeError: у объекта 'str' нет атрибута 'decode'], поэтому она была запущена, но теперь во втором комментарии она дает мне эту ошибку [TypeError: ожидаемая строка или байтовый объект ] @WiktorStribiżew

Harnish Shah 25.06.2019 12:41

Вам нужно преобразовать строку байтов в строку UTF8 для работы со строками. Я вижу, у вас есть b'...' в вопросе, поэтому мой .decode("utf8").

Wiktor Stribiżew 25.06.2019 12:44

Извините, re.sub(r'\s+(?:=\s*;\s*)?', ' ', re.search(r'{\s*"\w+".*}', s.decode("UTF8"), re.S).group().strip()).replace('&q;= uot;','"'), см. ideone.com/ULtkk8

Wiktor Stribiżew 25.06.2019 12:49

но [ b'...' ] уже удален из-за вашего первого комментария. @ВикторСтрибижев

Harnish Shah 25.06.2019 12:56

См. ideone.com/ULtkk8, работает ли он должным образом?

Wiktor Stribiżew 25.06.2019 12:57

NameError: имя 's' не определено @WiktorStribiżew

Harnish Shah 25.06.2019 13:02

@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;','"')

Wiktor Stribiżew 25.06.2019 13:08

@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']

Harnish Shah 25.06.2019 13:25

Вы не используете мой код. Строка, конечно, не имеет свойства re. Попробуйте этот код: ideone.com/YwmJH3. Он не компилируется онлайн, он должен работать в вашей консоли.

Wiktor Stribiżew 25.06.2019 13:28

Давайте продолжить обсуждение в чате.

Harnish Shah 25.06.2019 13:41
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
16
1 007
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете значительно упростить свою задачу с помощью библиотеки 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, &quot;EmojiFo=\r\nnt&quot;, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, NotoCo=\r\nlorEmoji, &quot;Segoe UI Symbol&quot;, &quot;Android Emoji&quot;, EmojiSymb=\r\nols;">\r\n<p style=3D"margin-top:0; margin-bottom:0"></p>\r\n<div>\r\n<div>{<br>\r\n&quot;vpn_detail&quot;:<br>\r\n&nbsp;&nbsp; &nbsp;{<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&quot;username&quot;:&quot;kushpate&q=\r\nuot;,&nbsp;&nbsp; &nbsp;<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&quot;tokens&quot;:&nbsp;&nbsp; &nbsp=\r\n;<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;[<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;85188605&quot;,<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;00422786&quot;,<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;94548619&quot;,<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;51249494&quot;,<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;HHEF0EA5&quot;,<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp=\r\n;&quot;2E09A81E&quot;<br>\r\n&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;],<br>\r\n&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&quot;cluster_name&quot;:&quot;bgl13-=\r\nvpn-cluster-2.cisco.com&quot;<br>\r\n&nbsp;&nbsp; &nbsp;}<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'

ПРИМЕЧАНИЯ:

  • Ваша входная строка представляет собой строку байтов, вам нужно преобразовать ее в строку Unicode UTF8, следовательно, необходимо MyStr.decode("utf8")
  • html2text.html2text(MyStr.decode("utf8")) очистит HTML от вашей строки, вы сразу получите свой JSON
  • re.sub(r'(&q;=\s*uot;)|=\s*;\s*', lambda x: '"' if x.group(1) else '', MyStrTxt) удаляет все вхождения =; с пробелами между ними, если они есть, или заменяет &q;=+ноль или более пробелов+uot; настоящим " символом.

Спасибо за ответ @WiktorStribizew, но я не хочу удалять вручную, потому что каждый раз, когда я читаю электронную почту с помощью python, эти данные JSON будут разными, но формат тот же, поэтому как я могу получить те же данные JSON из данных HTML, это мой вопрос . Ваш код дает мне ответ только [kushate], в то время как мне нужны все данные JSON.

Harnish Shah 25.06.2019 14:39

@ХарнишШах print(js). Пожалуйста, поиграйтесь с кодом. Очень легко print() выбрать любую интересующую вас переменную.

Wiktor Stribiżew 25.06.2019 14:40

да Это работает. Спасибо @Wiktor за лучшее решение.

Harnish Shah 25.06.2019 15:35

Другие вопросы по теме