如何将原始 javascript 对象转换为 python 字典?

IT技术 javascript python json web-scraping
2021-02-03 17:44:39

当屏幕抓取某个网站时,我从<script>标签中提取数据
我得到的数据不是标准JSON格式。我无法使用json.loads().

# from
js_obj = '{x:1, y:2, z:3}'

# to
py_obj = {'x':1, 'y':2, 'z':3}

目前,我使用regex将原始数据转换为JSON格式。
但是当我遇到复杂的数据结构时,我感觉很糟糕。

你有更好的解决方案吗?

6个回答

demjson.decode()

import demjson

# from
js_obj = '{x:1, y:2, z:3}'

# to
py_obj = demjson.decode(js_obj)

jsonnet.evaluate_snippet()

import json, _jsonnet

# from
js_obj = '{x:1, y:2, z:3}'

# to
py_obj = json.loads(_jsonnet.evaluate_snippet('snippet', js_obj))

ast.literal_eval()

import ast

# from
js_obj = "{'x':1, 'y':2, 'z':3}"

# to
py_obj = ast.literal_eval(js_obj)
demjson 和 jsonnet 的链接已失效
2021-03-14 17:44:39
demjson 给 Python 3 带来了问题,因为 Setuptools 已经取消了对 2to3 的支持。所以对于现在使用 python 3.X 的人来说,它可能不是一个有效的替代方案。
2021-04-08 17:44:39
JSON 不支持循环对象
2021-04-13 17:44:39

今天下午我面临同样的问题,我终于找到了一个很好的解决方案。那是JSON5

JSON5 的语法更类似于原生 JavaScript,因此可以帮助您解析非标准的 JSON 对象。

您可能想查看pyjson5

@Inventor 你能发布一个例子来说明它是如何工作的吗?
2021-03-30 17:44:39
这是最快的库。我尝试使用 demjson,我的脚本运行了 10.5 秒。Pyjson5 在 0.004s 内完成了这个任务。
2021-04-05 17:44:39

这可能不会在任何地方都有效,但作为开始,这里有一个简单的正则表达式,它应该将键转换为带引号的字符串,以便您可以传递到 json.loads。或者这就是你已经在做的事情?

In[70] : quote_keys_regex = r'([\{\s,])(\w+)(:)'

In[71] : re.sub(quote_keys_regex, r'\1"\2"\3', js_obj)
Out[71]: '{"x":1, "y":2, "z":3}'

In[72] : js_obj_2 = '{x:1, y:2, z:{k:3,j:2}}'

Int[73]: re.sub(quote_keys_regex, r'\1"\2"\3', js_obj_2)
Out[73]: '{"x":1, "y":2, "z":{"k":3,"j":2}}'

使用json5

import json5

js_obj = '{x:1, y:2, z:3}'

py_obj = json5.loads(js_obj)

print(py_obj)

# output
# {'x': 1, 'y': 2, 'z': 3}

如果您node在系统上可用,您可以要求它为您评估 javascript 表达式,并打印字符串化的结果。然后可以将生成的 JSON 提供给json.loads

def evaluate_javascript(s):
    """Evaluate and stringify a javascript expression in node.js, and convert the
    resulting JSON to a Python object"""
    node = Popen(['node', '-'], stdin=PIPE, stdout=PIPE)
    stdout, _ = node.communicate(f'console.log(JSON.stringify({s}))'.encode('utf8'))
    return json.loads(stdout.decode('utf8'))