【问题标题】:What is the most efficient way to extract info from complex JSON files?从复杂的 JSON 文件中提取信息的最有效方法是什么?
【发布时间】:2023-03-05 21:44:01
【问题描述】:

我是 Python 新手,正在努力从 dict 文件中提取某些信息。

我有数百万个存储文本数据的 JSON 文件。所有 JSON 文件都具有相似的结构。结构上有很多变化。对于每个 JSON 文件,我想从特定键中提取所有文本字符串并将它们存储为字典。

下面的json1json2 是简化的示例。我一直在做的是从 JSON 文件中抽取样本,分析它们,编写大量 if 语句,试图包含所有可能的变化。但是,我发现它效率低下,并且仍然无法包含所有场景。我想知道是否有一种通用的方法可以使用键 "text" 搜索和提取值。

json1 = {
        "section": {
                   "heading":{"lvl":"A1", "text":"today"},
                   "paragraph":[
                                {"color":"green",  "text":"yesterday"},
                                {"color":"purple", "text":"tomorrow"}
                               ]
                   }
         }

json2 = {
        "paragraph":{"text":"everyday", "color": "black"}
        }

换句话说,我想得到一个包含所有文本字符串的字典,其中的键为“文本”。对于json1,我想得到{"json1":"today yesterday tomorrow"}。对于json2,我想得到{"json2":"everyday"}

非常感谢任何帮助。

【问题讨论】:

  • 您想要set 还是dict 作为结果?你已经显示了set
  • @juanpa.arrivillaga 我想要一个dict 作为结果。我已经修复了我的描述。很抱歉造成混乱。
  • 现在你有一个dict,其中json对象的名称作为键(奇怪)和一个由每个"text"值连接并用逗号连接的字符串......你确定那正是你想要的?这听起来不是特别有用,尤其是因为它是一个具有单个键值对的字典......

标签: python json dictionary


【解决方案1】:

如果您什么都不知道,并且结构可能如您所暗示的那样随意,那么您必须访问每个节点并检查。这可以使用递归以通用方式实现。这是实现它的快速而肮脏的功能:

In [4]: def extract_text(obj, acc):
    ...:     if isinstance(obj, dict):
    ...:         for k, v in obj.items():
    ...:             if isinstance(v, (dict, list)):
    ...:                 extract_text(v, acc)
    ...:             elif k == "text":
    ...:                 acc.append(v)
    ...:     elif isinstance(obj, list):
    ...:         for item in obj:
    ...:             extract_text(item, acc)
...:       

你会如何使用它:

In [5]: acc1 = []

In [6]: extract_text(json1, acc1)

In [7]: acc1
Out[7]: ['yesterday', 'tomorrow', 'today']

In [8]: acc2 = []

In [9]: extract_text(json2, acc2)

In [10]: acc2
Out[10]: ['everyday']

请注意,您的问题与 JSON 没有任何关系,JSON 是一种基于文本的数据序列化格式。您已经在处理反序列化数据和 python 数据结构。无论如何,如果您真的想要问题中的结果,您可以这样做:

In [11]: {"json1": ",".join(acc1)}
Out[11]: {'json1': 'yesterday,tomorrow,today'}

或者你喜欢加入的任何分隔符,比如一个简单的空格:

In [12]: {"json1": " ".join(acc1)}
Out[12]: {'json1': 'yesterday tomorrow today'}

【讨论】:

    【解决方案2】:

    如果您对 json 文件的结构一无所知,我建议您转储内容并在列表中搜索。一个快速的解决方案如下。它只假设'text' 键对应一个单词条目。

    import pickle
    import json
    
    # Open .json file
    f = open("myjson.json")
    # Load the content
    info = json.load(f)
    # Dump the content as a list of words
    info_list = pickle.dumps(info).split('\n')
    # Whenever you see a 'text', collect the second next item
    texts = [info_list[i+2][1:] for i,a in enumerate(info_list) if a.find('text')>0]
    # Output the result
    print texts
    

    每个 json 文件的输出变为:

    In [1]: texts
    Out[1]: ['yesterday', 'tomorrow', 'today']
    

    【讨论】:

    • 这是一种非常老套和脆弱的方法。它依赖于相同的pickle 格式,这在您编写的python 3 上不起作用。例如,我无法重现您的结果,这可能是因为泡菜使用了不同的协议。我在 Python 2.7.12 上。
    猜你喜欢
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 2012-07-13
    • 2014-02-16
    • 2021-10-16
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多