Как найти объект JSON в тексте с помощью Python - PullRequest
0 голосов
/ 17 января 2019

Я пытаюсь разобрать объект JSON из текста с помощью регулярного выражения Python. Я нашел этот матч:

'\{(?:[^{}]|(?R))*\}'

но в python я получаю эту ошибку:

re.error: unknown extension ?R at position 12

См. Соответствие регулярному выражению в этом примере регулярного выражения .

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Вы нашли регулярное выражение, использующее синтаксис, который не поддерживается модулем стандартной библиотеки Python re.

Когда вы посмотрите на ссылку regex101, вы увидите, что шаблон работает при использовании библиотеки PRCE , а проблемный синтаксис (?R), который выдает ошибку, использует функцию под названием рекурсии . Эта функция поддерживается только подмножеством двигателей регулярных выражений .

Вы можете установить regex библиотеку , альтернативный механизм регулярных выражений для Pythont, который явно поддерживает этот синтаксис:

>>> import regex
>>> pattern = regex.compile(r'\{(?:[^{}]|(?R))*\}')
>>> pattern.findall('''\
... This is a funny text about stuff,
... look at this product {"action":"product","options":{...}}.
... More Text is to come and another JSON string
... {"action":"review","options":{...}}
... ''')
['{"action":"product","options":{...}}', '{"action":"review","options":{...}}']

Другой вариант - просто попытаться декодировать любой раздел, начинающийся с {, используя метод JSONDecoder.raw_decode() ; см. Как использовать модуль 'json' для чтения по одному объекту JSON за раз? для примера подхода. В то время как рекурсивное регулярное выражение может найти JSON- , например текст, подход декодера позволит вам извлечь только допустимый текст JSON.

Вот функция генератора, которая делает именно это:

from json import JSONDecoder

def extract_json_objects(text, decoder=JSONDecoder()):
    """Find JSON objects in text, and yield the decoded JSON data

    Does not attempt to look for JSON arrays, text, or other JSON types outside
    of a parent JSON object.

    """
    pos = 0
    while True:
        match = text.find('{', pos)
        if match == -1:
            break
        try:
            result, index = decoder.raw_decode(text[match:])
            yield result
            pos = match + index
        except ValueError:
            pos = match + 1

Демо-версия:

>>> demo_text = """\
This is a funny text about stuff,
look at this product {"action":"product","options":{"foo": "bar"}}.
More Text is to come and another JSON string, neatly delimited by "{" and "}" characters:
{"action":"review","options":{"spam": ["ham", "vikings", "eggs", "spam"]}}
"""
>>> for result in extract_json_objects(demo_text):
...     print(result)
...
{'action': 'product', 'options': {'foo': 'bar'}}
{'action': 'review', 'options': {'spam': ['ham', 'vikings', 'eggs', 'spam']}}
0 голосов
/ 17 января 2019

Это потому, что модуль python re довольно слабый и не поддерживает подпрограммы и рекурсию. Попробуйте вместо него модуль pypi regex. Это скомпилирует ваше регулярное выражение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...