2017-07-05 1 views
1
  1. Ich habe eine Datei (https://pastebin.com/STgtBRS8), in dem ich für alle Vorkommen des Wortes „silencedetect“ suchen müssen.Parse eine Datei für alle Vorkommen einer Zeichenkette und erzeugen Schlüsselwerte in JSON

  2. Ich muss dann eine JSON-Datei generieren, die die Schlüsselwerte "silence_start", "silence_end" und "silence_duration" enthält.

Die JSON-Datei wie etwa wie folgt aussehen:

[ 
{ 
"id": 1, 
"silence_start": -0., 
"silence_end": 2.2059, 
"silence_duration": 2.21828 
}, 
{ 
"id": 2, 
"silence_start": 5.79261, 
"silence_end": 6.91955, 
"silence_duration": 1.12694, 
} 
] 

Dies ist, was ich versucht habe:

with open('volume_data.csv', 'r') as myfile: 
    data = myfile.read().replace('\n', '') 

for line in data: 
    if "silencedetect" in data: 
     #read silence_start, silence_end, and silence_duration and put in json 

Ich bin nicht in der Lage, die drei Schlüssel-Wert-Paare zu assoziieren mit jeder "Silencedetect". Wie kann ich die Schlüsselwerte analysieren und sie im JSON-Format erhalten?

+1

sieht nicht als 'csv' Datei – RomanPerekhrest

+0

@RomanPerekrest: Ja, aber ich habe es als eins betrachtet. Es könnte auch .txt sein. Ignoriere die Erweiterung für jetzt. – pikaraider

Antwort

2

können Sie für es regex. es funktioniert für mich auf

import re 

with open('volume_data.csv', 'r') as myfile: 
    data = myfile.read() 

d = re.findall('silence_start: (-?\d+\.\d+)\n.*?\n?\[silencedetect @ \w{14}\] silence_end: (-?\d+\.\d+) \| silence_duration: (-?\d+\.\d+)', data) 
print d 

Sie sie in einem json indem

out = [{'id': i, 'start':a[0], 'end':a[1], 'duration':a[2]} for i, a in enumerate(d)] 
import json 
print json.dumps(out) # or write to file or... whatever 

Ausgang setzen könnte:

'[{"duration": "2.21828", "start": "-0.", "end": "2.2059", "id": 0}, {"duration": "1.12694", "start": "5.79261", "end": "6.91955", "id": 1}, {"duration": "0.59288", "start": "8.53256", "end": "9.12544", "id": 2}, {"duration": "1.0805", "start": "9.64712", "end": "10.7276", "id": 3}, {"duration": "1.03406", "start": "12.6657", "end": "13.6998", "id": 4}, {"duration": "0.871519", "start": "19.2602", "end": "20.1317", "id": 5}' 

EDIT: fixiert ein Fehler behoben, einige Spiele, weil der verpassten frame=.. Linie fiel zwischen dem Beginn und dem Ende des Spiels

1

Komplex Lösung re.findall und enumerate Funktionen:

import re, json 

with open('volume_data.txt', 'r') as f: 
    result = [] 
    pat = re.compile(r'(silence_start: -?\d+\.\d+).+?(silence_end: -?\d+\.\d+).+?(silence_duration: -?\d+\.\d+)') 
    silence_items = re.findall(pat, f.read().replace('\n', '')) 
    for i,v in enumerate(silence_items): 
     d = {'id': i+1} 
     d.update({pair[:pair.find(':')]: float(pair[pair.find(':')+2:]) for pair in v}) 
     result.append(d) 

    print(json.dumps(result, indent=4)) 

Der Ausgang:

[ 
    { 
     "id": 1, 
     "silence_end": 2.2059, 
     "silence_duration": 2.21828, 
     "silence_start": -0.
    }, 
    { 
     "id": 2, 
     "silence_end": 6.91955, 
     "silence_duration": 1.12694, 
     "silence_start": 5.79261 
    }, 
    { 
     "id": 3, 
     "silence_end": 9.12544, 
     "silence_duration": 0.59288, 
     "silence_start": 8.53256 
    }, 
    { 
     "id": 4, 
     "silence_end": 10.7276, 
     "silence_duration": 1.0805, 
     "silence_start": 9.64712 
    }, 
    { 
     "id": 5, 
     "silence_end": 13.6998, 
     "silence_duration": 1.03406, 
     "silence_start": 12.6657 
    }, 
    { 
     "id": 6, 
     "silence_end": 20.1317, 
     "silence_duration": 0.871519, 
     "silence_start": 19.2602 
    }, 
    { 
     "id": 7, 
     "silence_end": 22.4305, 
     "silence_duration": 0.801859, 
     "silence_start": 21.6286 
    }, 
    ... 
] 
+1

Ich wusste nicht über 'Einzug = 4', das ist cool. Wie viele Datensätze finden Sie aus Interesse? – Stael

+0

@Stael, die letzte 'id' war' "id": 189' – RomanPerekhrest

+0

ich verpasste 4 wegen der frame = ... Zeile fiel in der Mitte – Stael

0

import re import json

mit offenem ('volume_data.csv', 'r') als Meinedat: data = myfile_read()

matcher = re.compile('(?P<g1>[silencedetect @ \w+?\])\s+?silence_start:\s+?(?P<g2>-?\d+?\.\d+?).*?\n([^\[]+?\n)?(?P=g1)\s+?silence_end:\s+?(?P<g3>-?\d+?\.\d+?).+?\|\s+?silence_duration:\s+?(?P<g4>-?\d+?\.\d+?).*?\n') 
matchiter= matcher.findall(data) 
#(1) (2) 
string="" 
for i, matchediter in enumerate(matchiter): 
    string+= '{"id": {},\n, "silence_start":{},\n"silence_end": {},\n"silence_duration":{}}'. format(i, matchediter.group(g2),matchediter.group(g3),matchediter.group(g4)). 

json.dumps(string) 

(1) Sie könnten einige Flags wie "re.IGNORECASE" übergeben, um Ihr Skript vor solchen Änderungen zu schützen.

(2) Ich bevorzuge nicht gierige Sequenzen Erkennungsmuster, kann es Auswirkungen auf Erkennung und Geschwindigkeit. Die Verwendung von benannten Gruppen ist eine Frage des persönlichen Geschmacks. Sie können von Nutzen sein, wenn Sie sich stattdessen dafür entscheiden, einen matcher-Vorgang zu verwenden, um read die read() -Option sofort zu formatieren, anstatt Iteration zu verwenden, um den Dateitext neu zu erstellen. Ich könnte die Ersatzzeichenfolge hinzufügen, wenn Sie es nicht herausfinden können. Sonst bevorzuge ich .group of match object, dafür wird es gemacht und kann die Namen verwenden, die Sie anstelle von g1, g2, g3, g4 wählen.

Insgesamt bevorzuge ich Fisher, wie es im Grunde für diese Art von Operation gemacht wird, finden alle Tupel der erfassten Gruppen, das ist schön, aber manchmal möchten Sie möglicherweise Informationen relativ zu der vollständigen Übereinstimmung, Muster, Positionsindex in der verwenden analysierter Text usw.

Edit: Ich machte die Regex robust zu jeder Zeichenfolge nach Durationszahlen und zu mehreren Leerzeichen hinzugefügt. Ich nehme auch die interkalierten Zeilen in Betracht, Sie können sie erfassen, indem Sie die Gruppe benennen, wenn Sie möchten. Es erfasst 189 Vorkommen, es gibt 190 "Stille Start", aber das letzte ist nicht gefolgt von Ende und Dauer Informationen.

+1

Sie haben getan, was ich zuerst getan habe. Beachten Sie, dass eine Zeile wie folgt aussieht: [silencedetect @ 0x7fe7a4f00ac0] silence_start: 732.925 Frame = 22123 fps = 1001 q = -0,0 Größe = N/A Zeit = 00: 12: 18,17 Bitrate = N/A Geschwindigkeit = 33,4x [Silencedetect @ 0x7fe7a4f00ac0] Silence_end: 738,673 | silence_duration: 5.74771' was glaubst du nicht? – Stael

+1

auch, auch nach ein paar Syntaxfehlern (es ist ein 'fehl am Platz und Sie vergaßen zu \ einer Ihrer [) Ich bekomme 'schlechtes Zeichen in Backref-Gruppenname' '' – Stael

+0

Ich nahm Ihren Beitrag nicht als Beispiel, Ich habe lange gebraucht, um mir richtig zu schreiben, denn ich bin eher daran gewöhnt, Fragen zu stellen, als diese hier zu beantworten. Sie haben einen relevanten Punkt in dieser Zeile, ich kann ihn nicht zuordnen. Aber trotzdem habe ich es vorgezogen, meine Regex mit dem Silencedetect-Teil zu starten. Ich werde wieder meinen Beitrag bearbeiten, wenn es möglich ist, zusätzliche Zeichen zu berücksichtigen. Bei Fehlern scheint, dass ich den richtigen Ausdruck nicht aus meiner Zwischenablage kopiert habe. Wie dumm von mir. –

1

Ihre Daten Unter der Annahme, bestellt wird, können Sie es einfach Strom-analysieren, keine Notwendigkeit für regex und Laden der gesamten Datei überhaupt:

import json 

parsed = [] # a list to hold our parsed values 
with open("entries.dat", "r") as f: # open the file for reading 
    current_id = 1 # holds our ID 
    entry = None # holds the current parsed entry 
    for line in f: # ... go through the file line by line 
     if line[:14] == "[silencedetect": # parse the lines starting with [silencedetect 
      if entry: # we already picked up silence_start 
       index = line.find("silence_end:") # find where silence_end starts 
       value = line[index + 12:line.find("|", index)].strip() # the number after it 
       entry["silence_end"] = float(value) # store the silence_end 
       # the following step is optional, instead of parsing you can just calculate 
       # the silence_duration yourself with: 
       # entry["silence_duration"] = entry["silence_end"] - entry["silence_start"] 
       index = line.find("silence_duration:") # find where silence_duration starts 
       value = line[index + 17:].strip() # grab the number after it 
       entry["silence_duration"] = float(value) # store the silence_duration 
       # and now that we have everything... 
       parsed.append(entry) # add the entry to our parsed list 
       entry = None # blank out the entry for the next step 
      else: # find silence_start first 
       index = line.find("silence_start:") # find where silence_start, well, starts 
       value = line[index + 14:].strip() # grab the number after it 
       entry = {"id": current_id} # store the current ID... 
       entry["silence_start"] = float(value) # ... and the silence_start 
       current_id += 1 # increase our ID value for the next entry 

# Now that we have our data, we can easily turn it into JSON and print it out if needed 
your_json = json.dumps(parsed, indent=4) # holds the JSON, pretty-printed 
print(your_json) # let's print it... 

Und Sie erhalten:

[ 
    { 
     "silence_end": 2.2059, 
     "silence_duration": 2.21828, 
     "id": 1, 
     "silence_start": -0.
    }, 
    { 
     "silence_end": 6.91955, 
     "silence_duration": 1.12694, 
     "id": 2, 
     "silence_start": 5.79261 
    }, 
    { 
     "silence_end": 9.12544, 
     "silence_duration": 0.59288, 
     "id": 3, 
     "silence_start": 8.53256 
    }, 
    { 
     "silence_end": 10.7276, 
     "silence_duration": 1.0805, 
     "id": 4, 
     "silence_start": 9.64712 
    }, 
    # 
    # etc. 
    # 
    { 
     "silence_end": 795.516, 
     "silence_duration": 0.68576, 
     "id": 189, 
     "silence_start": 794.83 
    } 
] 

Halten Beachten Sie, dass JSON die Reihenfolge der Daten nicht abonniert (noch Python dict vor v3.5), so dass die id nicht unbedingt an erster Stelle erscheinen wird, aber die Datengültigkeit ist genau das gleiche.

Ich habe absichtlich die ursprüngliche entry Erstellung getrennt, so dass Sie collections.OrderedDict als Drop-in-Ersatz (d. H. entry = collections.OrderedDict({"id": current_id})) verwenden können, um die Reihenfolge zu erhalten, wenn Sie das wünschen.

Verwandte Themen