2016-06-25 4 views
3

Ich brauche rekursiv gehen eine JSON-Dateien (post Antworten von einer API) Trog, die Saiten zu extrahieren, die haben [ „text“] als Schlüssel {"text":"this is a string"}rekursive Spaziergang durch eine JSON-Datei ausgewählt Strings extrahiert

Ich muß Beginnen Sie mit der Analyse der Quelle, die das älteste Datum in den Metadaten hat, extrahieren Sie die Zeichenfolgen aus dieser Quelle, und wechseln Sie dann zur zweitältesten Quelle und so weiter. Die JSON-Datei könnte schlecht verschachtelt sein, und die Ebene, auf der sich die Zeichenfolgen befinden, kann sich von Zeit zu Zeit ändern.

Problem: Es gibt viele Schlüssel namens ["Text"] und ich brauche nicht alle von ihnen, ich brauche nur diejenigen, die Werte als Zeichenfolge haben. Besser, der "text": "string" brauche ich IMMER im selben Objekt {} einer "type":"sentence". Siehe Bild.

Was ich frage

Ändern Sie den zweiten Code unten, um rekursiv die Datei zu gehen und extrahieren nur die [ „text“] Werte, wenn sie im selben Objekt sind {} zusammen mit „type“:“ Satz".

Im Folgenden ein Ausschnitt aus JSON-Datei (in grün der Text, den ich und die medatada benötigen, in rot die, die ich nicht brauchen, um zu extrahieren): http://pastebin.com/0NS5BiDk:

screenshot of contents of JSON file

Link zum vollständigen JSON Probe

Was ich bisher getan haben:

1) Der einfache Weg: verwandle die jSON-Datei in String und die Suche nach Inhalt zwischen den doppelten Anführungszeichen („“), weil in allen json Beitrag Antworten die „Strings“ I Notwendigkeit sind die nur solche, die zwischen doppelten Anführungszeichen stehen. Diese Option verhindert jedoch, dass ich die Ressourcen vorher bestellen kann, ist also nicht gut genug.

r1 = s.post(url2, data=payload1) 
j = str(r1.json()) 

sentences_list = (re.findall(r'\"(.+?)\"', j)) 

numentries = 0 
for sentences in sentences_list: 
    numentries += 1 
    print(sentences) 
    print(numentries) 

2) Smarter Weg: gehen rekursiv eine JSON-Datei Trog und Dekomprimierung der [ "text"] Werte

def get_all(myjson, key): 
    if type(myjson) is dict: 
     for jsonkey in (myjson): 
      if type(myjson[jsonkey]) in (list, dict): 
       get_all(myjson[jsonkey], key) 
      elif jsonkey == key: 
       print (myjson[jsonkey]) 
    elif type(myjson) is list: 
     for item in myjson: 
      if type(item) in (list, dict): 
       get_all(item, key) 

print(get_all(r1.json(), "text")) 

Es extrahiert alle Werte, die [ "text"] als Key haben. Leider gibt es in der Datei andere Sachen (die ich nicht brauche), die ["text"] als Key haben. Daher gibt es Text zurück, den ich nicht brauche.

Bitte beraten.

UPDATE

I 2 Codes geschrieben haben, um die Liste der Objekte, die von einem bestimmten Schlüssel zu sortieren. Der erste sortiert nach dem 'Text' des XML. Der zweite Wert nach dem Wert "Zeitraum enthalten von".

Die erste funktioniert, aber ein paar der XMLs, auch wenn sie in der Anzahl höher sind, haben tatsächlich Dokumente in älter als ich erwartet hatte.

Für den 2. Code ist das Format von 'Zeitraum von enthalten' nicht konsistent und manchmal ist der Wert überhaupt nicht vorhanden. Der zweite gibt mir auch einen Fehler, aber ich kann nicht herausfinden, warum - string indices must be integers.

# 1st code (it works but not ideal) 

j=r1.json() 

list = [] 
for row in j["tree"]["children"][0]["children"]: 
    list.append(row) 

newlist = sorted(list, key=lambda k: k['text'][-9:]) 
print(newlist) 

# 2nd code I need something to expect missing values and to solve the 
# list index error 
list = [] 
for row in j["tree"]["children"][0]["children"]: 
    list.append(row) 

def date(key): 
    return dparser.parse((' '.join(key.split(' ')[-3:])),fuzzy=True) 

def order(list_to_order): 
    try: 
     return sorted(list_to_order, 
         key=lambda k: k[date(["metadata"][0]["value"])]) 
    except ValueError: 
     return 0 

print(order(list)) 
+1

Bitte bearbeiten Sie Ihre Frage und fügen Sie ein Beispiel von JSON ein, das als Text geparst werden soll - nur ein Screenshot ist nicht genug. – martineau

+0

@martineau, ist es nicht genug das Bild, das ich bereits geladen habe? Ich bin mir nicht sicher, ob ich Ihre Anfrage verstehe, tut mir leid. bitte erkläre. BTW Ich benutze Python 3.5 – ganesa75

+0

@martineau, wie kann ich die gesamte JSON-Datei laden? – ganesa75

Antwort

2

Ich denke, das wird tun, was Sie wollen, was die Auswahl der richtigen Strings angeht.Ich änderte auch die Art, wie die Typüberprüfung durchgeführt wurde, um isinstance() zu verwenden, was als ein besserer Weg angesehen wird, dies zu tun, da sie objektorientierten Polymorphismus unterstützt.

import json 
_NUL = object() # unique value guaranteed to never be in JSON data 

def get_all(myjson, kind, key): 
    """ Recursively find all the values of key in all the dictionaries in myjson 
     with a "type" key equal to kind. 
    """ 
    if isinstance(myjson, dict): 
     key_value = myjson.get(key, _NUL) # _NUL if key not present 
     if key_value is not _NUL and myjson.get("type") == kind: 
      yield key_value 
     for jsonkey in myjson: 
      jsonvalue = myjson[jsonkey] 
      for v in get_all(jsonvalue, kind, key): # recursive 
       yield v 
    elif isinstance(myjson, list): 
     for item in myjson: 
      for v in get_all(item, kind, key): # recursive 
       yield v  

with open('json_sample.txt', 'r') as f: 
    data = json.load(f) 

numentries = 0 
for text in get_all(data, "sentence", "text"): 
    print(text) 
    numentries += 1 

print('\nNumber of "text" entries found: {}'.format(numentries)) 
+0

danke es funktioniert. Kannst du beraten, wie man die Zahlen überprüft? Es gibt ein paar bedingte Schleifen und nicht sicher, wo Ort Numerien + = 1 – ganesa75

+0

Danke, es funktioniert. 1. können Sie beraten, wie Sie die Numerien überprüfen? es gibt ein paar bedingte Schleifen und ich bin mir nicht sicher, wo ich Platz "numentries + = 1" habe 2. Ich muss noch die Ressourcen bestellen, bevor Sie den "Text" extrahieren. Wie kann ich es tun? Ich habe die JSON-Datei untersucht und festgestellt, dass der 'resourceType': 'XML', 'text': 'S5CV0280P0.xml' mir diese Reihenfolge geben kann. Ich meine, idealerweise sollte Ihr Code den "Text" vorher auf 0280 und dann auf 0281 analysieren. In der ursprünglichen JSON-Datei ist die .xml nicht in Ordnung. – ganesa75

+0

Ich habe meine Antwort geändert, um die Anzahl der Einträge zu ermitteln, ohne sie zu zählen - Es speichert nur jede in einer Liste und verwendet die Länge dieser Liste am Ende, um 'Numerien' zu bestimmen. – martineau

Verwandte Themen