Как извлечь JSON из скрипта с помощью Python?

#python #json #regex

#python #json #регулярное выражение

Вопрос:

Я анализирую очищенную HTML-страницу, содержащую скрипт с JSON внутри. Этот JSON содержит всю информацию, которую я ищу, но я не могу понять, как извлечь действительный JSON.

Минимальный пример:

 my_string = '
        (function(){
          window.__PRELOADED_STATE__ = window.__PRELOADED_STATE__ || [];
          window.__PRELOADED_STATE__.push(
        
           { *placeholder representing valid JSON inside* }
        );
        })()
'
 

json внутри действителен в соответствии с jsonlinter.

Результат должен быть загружен в словарь:

 import json
import re
my_json = re.findall(r'.*(?={").*', my_string)[0] // extract json
data = json.loads(my_json)
// print(data)
 

регулярное выражение: https://regex101.com/r/r0OYZ0/1

Эта попытка приводит к:

 >>> data = json.loads(my_json)
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/code.py", line 90, in runcode
    exec(code, self.locals)
  File "<console>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/__init__.py", line 357, in loads
    return _default_decoder.decode(s)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 7 (char 6)
 

Как можно извлечь и загрузить JSON из строки с помощью Python 3.7.x?

Комментарии:

1. Вы должны использовать json.loads метод (не забудьте s ). Но ваша строка, похоже, не является допустимым json.

2. Это правда, пожалуйста, прочитайте вопрос еще раз.

3. JSON, который у вас есть в вашем примере регулярных выражений, не является допустимым JSON: {"publicRuntimeConfig":{"public }

Ответ №1:

вы можете попытаться извлечь это регулярное выражение, это очень простой случай и может не отвечать на все возможные варианты json:

 my_string = '''
        (function(){
          window.__PRELOADED_STATE__ = window.__PRELOADED_STATE__ || [];
          window.__PRELOADED_STATE__.push(
        
            {"tst":{"f":3}}
        );
        })()
'''
result = re.findall(r"push(([{[].*:.*[}]]))",string3)[0]
result
>>> '{ "tst":{"f":3}}'
 

чтобы разобрать его в словаре сейчас:

 import json 

dictionary = json.loads(result)
type(dictionary)
>>>dict
 

Комментарии:

1. Да, Json содержит экранированные символы, к сожалению, вы знаете, как удалить escape-знак?

2. json содержит: : [«строка 5 ‘-mono. D

3. Я обновил вопрос и связался с регулярным выражением101 с полным JSON

4. Это потому, что регулярное выражение не в порядке. Внешний вид фиксирует заключительную скобку. Если вы удалите) в конце, он будет проверен в соответствии с jsonlint.com

5. Вы правы! Похоже, у меня есть другое регулярное выражение, которое работает. .*(?:push()(.*)) Какой из них вы бы порекомендовали использовать и почему?

Ответ №2:

Взгляните на приведенное ниже. Обратите внимание, что это { *placeholder representing valid JSON inside* } должен быть действительный JSON.

 my_string = '''
        <script>
            (function(){
              window.__PRELOADED_STATE__ = window.__PRELOADED_STATE__ || [];
              window.__PRELOADED_STATE__.push(
            
               {"foo":["bar1", "bar2"]}
            );
            })()
         </script>
'''

import re, json

my_json = re.findall(r'.*(?={").*', my_string)[0].strip()
data = json.loads(my_json)
print(data)
 

Вывод:

 {'foo': ['bar1', 'bar2']}
 

Комментарии:

1. Приближаемся. Теперь у меня есть аналогичное регулярное выражение: .*(?:push()(.*)(?<=)). Вы правы насчет допустимого json. Внутри JSON есть escape-символ: [«строка 5 ‘-mono. Знаете ли вы функцию, которая удаляет их?

2. Может быть, вы можете просто использовать str.replace()

Ответ №3:

my_string Предоставленный здесь недопустимый JSON. Для допустимого JSON вы можете использовать json.loads(JSON_STRING)

 import json

d = json.loads('{"test":2}')
print(d) # Prints the dictionary `{'test': 2}`
 

Комментарии:

1. Ну, в этом весь смысл! Пожалуйста, прочитайте мой вопрос еще раз, «json внутри действителен». Мне нужно выяснить, как удалить код javascript вокруг него.

2. Вопрос был отредактирован, чтобы уточнить это после того, как я опубликовал этот ответ.

3. Да, после того, как я увидел ваш ответ, я попытался прояснить ситуацию. Может помочь регулярное выражение, есть идеи?