我有一个行文件如下:
{u'af': 4, **[a lots of attribute i don't need]**, u'prb_id': **6092**, u'result': [{u'result': [{u'rtt': 0.266, u'ttl': 255, u'from': u'**208.80.155.67**', u'size': 28}, {u'rtt': 0.413, u'ttl': 255, u'from': u'208.80.155.67', u'size': 28}, {u'rtt': 1.565, u'ttl': 255, u'from': u'208.80.155.67', u'size': 28}], u'hop': 1}, {u'result': [{u'rtt': 68.468, u'ttl': 254, u'from': u'**206.126.237.239**', u'size': 68}, {u'rtt': 67.844, u'ttl': 254, u'from': u'206.126.237.239', u'size': 68}, {u'rtt': 70.378, u'ttl': 254, u'from': u'206.126.237.239', u'size': 68}], u'hop': 2}[**a lots of attribute i don't need**]}
我尝试将其解析为JSON
文件,其中包含:
data = []
with open('prova1') as f:
for line in f:
data.append(json.loads(line))
但我得到以下ValueError
:
ValueError: Expecting property name: line 1 column 2 (char 1)
我需要的是取值prb_id
和字段中的每个值,避免重复。
我的目标是获取具有以下格式的CSV文件:
6092,208.80.155.67,206.126.237.239
如何使用Python解析它?
答案 0 :(得分:1)
这不是JSON(*),因此json模块无法对其进行解码。但它看起来像Python语法,所以ast.literal_eval
可以很好地完成它,但是你将失去字段的顺序:
data = []
with open('prova1') as f:
for line in f:
data.append(ast.literal_eval(line))
如果您以后想要提取所有 from
字段,并且您的结构可以包含嵌套的字典和列表,则可以使用以下方式递归提取它们:
def parse_for_key(m, id, k):
""" m is the dictionnary to parse, k the key for the id, k the key to extract"""
def _do_parse(m, k, l): # recursive function passing the list being computed
if isinstance(m, list): # process for a list
for elt in m: # recurse in all elements from the list
_do_parse(elt, k, l)
elif isinstance(m, dict): # process for a dictionnary
if (k in m) and not (m[k] in l): # evt. add value for key if not already there
l.append(m[k])
for elt in m.values():
_do_parse(elt, k, l) # and recurse in values
return l # return the list
return _do_parse(m, k, [m[id]])
然后您可以使用parse_for_key(m, 'prb_id', 'from')
,其中m是一行的litteral_eval
的结果,并且会得到类似的结果:
[6026, '83.212.7.42', '83.212.7.41', '62.217.100.63', '83.97.88.69', '62.40.112.165', ...]
(*)JSON要求标识符包含在 double 引号("
)中,并且没有unicode字符串u
前缀的概念。
答案 1 :(得分:0)
问题是json解析器期望对象'作为字符串和字符串的键在Json规范中不包含unicode前缀(参见http://www.json.org/json-en.html)
我不知道任何正确解析json解析unicode前缀的方法。
您的真实数据中是否有**
?如果没有,你仍然可以使用这个肮脏的技巧(我不确定它是否适用于所有情况):
import json
s = """{u'a': 1, u'l':[u'b', u'c']}"""
exec("d = {}".format(s))
print(d)
print(json.dumps(d))
输出:
{u' a':1,你':[u' b',' c']}
{" a":1," l":[" b"," c"]}
最好的方法当然是将格式良好的json作为输入,但我想你不能拥有它。
答案 2 :(得分:0)
这不是正确的JSON,它是Python用于打印字典的格式,但它不是有效的JSON。例如,JSON需要双引号,而不是单引号,JSON不允许u"string"
定义字符串。
选项1:将字符串转换为json(以说服自己这是错误的根源):
$ cat ttt.json
{u'af': 4, u'prb_id': 6092, u'result': [{u'result': [{u'rtt': 0.266, u'ttl': 255, u'from': u'208.80.155.67', u'size': 28}, {u'rtt': 0.413, u'ttl': 255, u'from': u'208.80.155.67', u'size': 28}, {u'rtt': 1.565, u'ttl': 255, u'from': u'208.80.155.67', u'size': 28}], u'hop': 1}, {u'result': [{u'rtt': 68.468, u'ttl': 254, u'from': u'206.126.237.239', u'size': 68}, {u'rtt': 67.844, u'ttl': 254, u'from': u'206.126.237.239', u'size': 68}, {u'rtt': 70.378, u'ttl': 254, u'from': u'206.126.237.239', u'size': 68}], u'hop': 2}]}
>>> import json
>>> a = open("ttt.json").read()
>>> json.loads(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/[...]__init__.py", line 309, in loads
return _default_decoder.decode(s)
File "/usr/local/[...]decoder.py", line 351, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/local/[...]decoder.py", line 367, in raw_decode
obj, end = self.scan_once(s, idx)
ValueError: Expecting property name: line 1 column 1 (char 1)
>>> # But after some replacements,
>>> json.loads(json.loads(re.sub("u'([a-zA-Z0-9_\.]*)'", r'"\1"', a)))
{'prb_id': 6092, 'result': [{'result': [{'rtt': 0.266, 'size': 28, 'from': '208.80.155.67', 'ttl': 255}, {'rtt': 0.413, 'size': 28, 'from': '208.80.155.67', 'ttl': 255}, {'rtt': 1.565, 'size': 28, 'from': '208.80.155.67', 'ttl': 255}], 'hop': 1}, {'result': [{'rtt': 68.468, 'size': 68, 'from': '206.126.237.239', 'ttl': 254}, {'rtt': 67.844, 'size': 68, 'from': '206.126.237.239', 'ttl': 254}, {'rtt': 70.378, 'size': 68, 'from': '206.126.237.239', 'ttl': 254}], 'hop': 2}], 'af': 4}
选项二(这是首选选项):使用ast
读取字符串:
>>> import ast
>>> ast.literal_eval(a)
{'prb_id': 6092, 'result': [{'result': [{'rtt': 0.266, 'size': 28, 'from': '208.80.155.67', 'ttl': 255}, {'rtt': 0.413, 'size': 28, 'from': '208.80.155.67', 'ttl': 255}, {'rtt': 1.565, 'size': 28, 'from': '208.80.155.67', 'ttl': 255}], 'hop': 1}, {'result': [{'rtt': 68.468, 'size': 68, 'from': '206.126.237.239', 'ttl': 254}, {'rtt': 67.844, 'size': 68, 'from': '206.126.237.239', 'ttl': 254}, {'rtt': 70.378, 'size': 68, 'from': '206.126.237.239', 'ttl': 254}], 'hop': 2}], 'af': 4}
>>>