iTunesXML 2 CSV Converter

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
kelvan
User
Beiträge: 3
Registriert: Mittwoch 30. Juli 2008, 23:04
Wohnort: Wien

Mittwoch 30. Juli 2008, 23:44

Hallo,

ich bin gerade neu dazu gestoßen. (Ich stelle mich vl später mal in einem eigenen Thread vor)

Vor Kurzem bemerkte ich das iTunes nur m3u und xml Export hat, ich hätte aber gerne einen CSV Export, mit Songbird konnte ich zwar die XML importieren, aber auch nicht als CSV exportieren. (Hab auf die schnelle auch sonst keien Converter gefunden)

Habe deswegen heute einen Converter gebastelt (der Aufbau der iTunes XML Datei ist schrecklich), natürlich mit Python (+lxml).

Falls jemand sowas gebrauchen kann, ist/wird auf sf.net gepublished(tolles Wort).

Habe noch irgendwo einen Bug, ca. alle 12k Zeilen schreibt er zuviel auf einmal. (Und OOorg kann kaum mehr als 65k Zeilen haben :(), aber selbst mit solchen Mengen war das konvertieren sehr schnell. Momentan wird nur Titel, Interpret, Album, Medientyp und Bit Rate exportiert (kann man aber leicht erweitern), was die csv Datei wesentlich kleiner macht als die XML.

Außerdem sollte ich ein paar ifs durch einen switch ersetzen, hat nicht geklappt(schrieb den content nicht in output[0] sondern in alle output[]) und ich hatte keine Lust/Zeit zum suchen.

Wäre toll wenn es irgendwer gebrauchen könnte, bzw. mich jemand auf mögliche Fehler oder "Unschönheiten" aufmerksam macht.

(Vorübergehend auf rafb.net hochgeladen)

mfg,
Kelvan

PS: Werde morgen dann vl noch meinen Vokabeltrainer vorstellen, ist aber noch sehr "lightweight" :)
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 31. Juli 2008, 01:10

Hallo kelvan, willkommen im Forum,

Ich finde die Inline-Kommentare sehr seltsam (sowas schreibt man über den zu kommentierenden Code nicht dahinter, wo der Editor es schon längst zwei Mal umgebrochen hat). Noch dazu solltestd du dringen alle ``global``-Aufrufe weglassen, ja besser sogar vergessen dass es ``global`` gibt (dafür gibt es ``return``). Die äußersten Klammern um die ``if``s würde man in Python weglassen.

Es wäre unter umständen auch praktisch die XML-Datei hereinpipen zu können und die Ausgabe dann auf Stdout bekommen.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
kelvan
User
Beiträge: 3
Registriert: Mittwoch 30. Juli 2008, 23:04
Wohnort: Wien

Donnerstag 31. Juli 2008, 10:57

Leonidas hat geschrieben:Hallo kelvan, willkommen im Forum,

Ich finde die Inline-Kommentare sehr seltsam (sowas schreibt man über den zu kommentierenden Code nicht dahinter, wo der Editor es schon längst zwei Mal umgebrochen hat). Noch dazu solltestd du dringen alle ``global``-Aufrufe weglassen, ja besser sogar vergessen dass es ``global`` gibt (dafür gibt es ``return``). Die äußersten Klammern um die ``if``s würde man in Python weglassen.

Es wäre unter umständen auch praktisch die XML-Datei hereinpipen zu können und die Ausgabe dann auf Stdout bekommen.
Danke für die Antwort, Kommentare hab ich mal geändert, Klammern sind entfernt, bin gerade am umschreiben wegen output, der Variableninhalt bleibt erhalten wenn eine function mehrmals verwendet wird (in dem fall output), oder?

wie macht man es wenn man mehrere sachen returnen will?
sollte wahrscheinlich mit class/object/etc machen, nehme ich an, ala output.Artist.set()

wie meinst du das im letzten Absatz?
der inhalt wird nach stdout (außer ich hab da was durcheinander gebracht) ausgegeben und sollte per "> file" in eine datei geschrieben werden. (oder meisnt du was anderes)

Code: Alles auswählen

import sys
from lxml import etree
#import elementtree.ElementTree as etree

def walk_tree(node, level, output, key):
    
    # Keys on Level4 are for a single Treck
    if (node.tag == "key") and (level == 4):
        # Save keyTag to allocate with next stringTag
        key = node.text
    
    # We are at the bitrateTag
    if (node.tag == "integer") and (key == "Bit Rate") and (level == 4):  
        # Save Bit Rate
        output[4] = node.text
    
    #We are at a string tag
    if (node.tag == "string") and (level == 4):
        # Find out what kind of string
        output[manage_output(key)] = node.text.encode( "utf-8" )
        
    if (node.tag == "dict") and (level == 3):
        print """,output[0],"";"",output[1],"";"",output[2],"";"",output[3],"";"",output[4],"""
        for i in range(0,4):
            output[i] = ""
        
    children = node.getchildren()
    for child in children:
        walk_tree(child, level + 1,output, key)

def manage_output(out_type):
    #out=lambda *x:sys.stdout.write(" ".join(map(str,x)))

    if out_type == "Name":
        return 0
    if out_type == "Artist":
        return 1
    if out_type == "Album":
        return 2
    if out_type == "Genre":
        return 3

def test(inFileName):
    doc = etree.parse(inFileName)
    root = doc.getroot()
    #global output
    output = ["Name","Artist","Album","Genre","Bit Rate[kbit/s]"]
    key = ""
    walk_tree(root, 0, output, key)

def main():
    args = sys.argv[1:]
    if len(args) != 1:
        print 'usage: python test.py infile.xml'
        sys.exit(-1)
    test(args[0])

if __name__ == '__main__':
    main()
Wo hab ich einen Fehler gemacht manage_output(key) gibt mir immer einen NoneType zurück :(
Scheinbar wird key nicht übergeben :/

mfg,
Kelvan

PS: Wie kann ich Text im Terminal ausgeben der nicht durch "> file" ins file geschrieben wird?
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 31. Juli 2008, 15:15

kelvan hat geschrieben:wie macht man es wenn man mehrere sachen returnen will?
sollte wahrscheinlich mit class/object/etc machen, nehme ich an, ala output.Artist.set()
Containertypen existieren. Etwa list, dict, set, eigene Objekte.
kelvan hat geschrieben:der inhalt wird nach stdout (außer ich hab da was durcheinander gebracht) ausgegeben und sollte per "> file" in eine datei geschrieben werden. (oder meisnt du was anderes)
Es wäre schön wenn man auch mittels ``< file`` eine Datei hineinschicken könnte.

Wenn ``manage_output`` None zurückgibt, dann liegt dass daran, dass out_type nichts von dem ist, worauf du es testest, die Funktion also bis zum Ende läuft und dann implizit None zurückgibt.
kelvan hat geschrieben:PS: Wie kann ich Text im Terminal ausgeben der nicht durch "> file" ins file geschrieben wird?
Du musst einen anderen Output-Stream verwenden, ``stderr``.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
kelvan
User
Beiträge: 3
Registriert: Mittwoch 30. Juli 2008, 23:04
Wohnort: Wien

Donnerstag 31. Juli 2008, 16:12

Leonidas hat geschrieben:Wenn ``manage_output`` None zurückgibt, dann liegt dass daran, dass out_type nichts von dem ist, worauf du es testest, die Funktion also bis zum Ende läuft und dann implizit None zurückgibt.
Hab's durchgeschaut liegt daran das key nicht gesetzt wurde, warum weiß ich nicht hat er vorher alles richtig gemacht.weiten

EDIT: key wird richtig gesetzt wird aber nicht richtig übergeben, beim darauffolgenden Durchlauf resettet er ihn. Vermute das test() da key resettet :(
Weiß jemand Rat wie ich das hinbiegen kann? (Die Pfuschversion vorher funktionierte ;), gebt mir keinen Grund zu pfuschen :twisted: )

mfg,
Kelvan
Antworten