Вы нашли регулярное выражение, использующее синтаксис, который не поддерживается модулем стандартной библиотеки 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']}}