使用python解析文件以获取CSV

时间:2016-11-28 11:32:38

标签: python json parsing

我有一个行文件如下:

{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解析它?

3 个答案:

答案 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}
>>>