Seite auslesen, ändern und ausgeben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Hallo Community,

ich arbeite gerade an einem kleinen Skript, welches als
Eingabe eine beliebe Web Seite erlaubt und dort dann jeden
Akkord, ja ich rede hier von Musik, um einen offset transponiert.

Das Transponieren eines belieben Akkordes funktioniert auch schon wunderbar.

Also:

Code: Alles auswählen

transpose("Bm", 1)
würde zuückgeben.

Nun will ich das ganze mit einer Web Seite kombinieren.

Wie gehe ich da am besten vor? Am besten wäre es natürlich, die Seite dann auch komplett auszugeben. Macht man das am besten mit Qts Webkit?

Nur her mit dem Input!

Danke!
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

Was verstehst du unter "mit einer Website kombinieren"? Willst du Daten von anderen Websites holen oder dein Tool als Webnservice für andere bereitstellen oder vllt. noch was anderes?
Karl
User
Beiträge: 252
Registriert: Freitag 29. Juni 2007, 17:49

Naja du kannst die Seite ja mit der urllib oder sonstigen Modulen deiner Wahl auslesen und im Quelltext die Akkorde rausfiltern (zB Regex)
Vielleicht, sofern es möglich ist, versuchen nur den Lied-Bereich zu transponieren, da man ja auch mal ein paar Anmerkungen zu einem Lied stehen hat, und man da nicht unbedingt die Akkorde transponieren muss.
Aber ansonsten sehe ich da kein Problem.
Du kannst die (veränderte) Seite dann ja sogar mit dem Pythonscript lokal abspeichern und mittels dem Modul webbrowser die Seite direkt öffnen.

Ansonsten wäre zB der Webservice praktisch:
"Lied hier rein kopieren" und man kopiert einfach das komplette Lied mit Akkorden. Dann als Ausgabe kriegt man das Lied mit transponierten Akkorden.
Du könntest dir ja auf Wikipedia mal die verschiedenen Akkordschreibweisen angucken: http://de.wikipedia.org/wiki/Akkordsymbol um dein Tool zu verbessern.
Außerdem musst du, wenn dort ein Akkord mit verändertem Basston steht (zB Am/B), diesen auch transponieren, da er sonst nicht unbedingt zum Akkord passt.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Hört sich interessant an! Werde mir die vorgeschlagenen Sachen mal angucken!
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Wie kann ich das Problem mit dem RegEx lösen.

Ich habe es probiert ohne reguläre Ausdrücke hinzubekommen, komme aber auf keinen grünen Zweig.

Ich habe in combinations (Liste) alle möglichen Kombinationen:

Hier ein Auszug:

Code: Alles auswählen

>>> print combinations
['C', 'C#', 'Db', 'D', 'D#', 'Eb', 'E', 'F', ...]
Wie kann ich diese nun über die Seite jagen lassen, falls eines gefunden wurde, ersetzen lassen duch ein aufruf der funktion transpose() ?

Danke!
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Simple Lösung (funktioniert nur mit Klartext und nicht mit HTML)

Code: Alles auswählen

for word in file_content.strip():
  if word in combinations: # btw, schlechter Variablennamen...
    transpose(word, -1)
Für HTML musst du halt noch einen Parser einsetzen, der dir Klartext generiert.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Irgendwie scheint es nicht zu klappen. Deine obige Variante ändern an der eigentlich eingabe doch gar nichts, ruft die Funktion auf und macht nichts mit ihr. Außerdem würde deine Variante zum Beispiel zuerst D erkennnen, obwohl es eigentlich Db7 ist.

In meinem Ansatz zerstückel ich alles:

Code: Alles auswählen

        temp = temp.split()
        
        i = 0
        for element in temp:            
            if element in combinations:
                temp[i] = transpose(element, 1)[0]
            i = i + 1
und füge es im nachhinein wieder zusammen, funktioniert auch soweit, leider gehen daduch alle leerzeichen, returns und tabs verloren.


Gibt es eine Möglichkeit, sodass split() auch spaces und tabs und returns mit integriert.

Also:

Code: Alles auswählen

"Hallo ich bins"
Wäre dann:

Code: Alles auswählen

["Hallo"], [" "], ["ich"], [" "], ["bins"]
So würde mein Skript zu 100 % korrekt funktioniren!
Andere Vorschläge? Vieeelen Dank!
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Ein Bsp. mit RegEx:

Code: Alles auswählen

import re
from functools import partial

CHORD_NUM = {'C': 0,'C#':1,'Db':1,'D':2,'D#':3,'Eb':3,'E':4,'E#':5,'Fb':4,'F':5,
        'F#':6,'Gb':6,'G':7,'G#':8,'Ab':8,'A':9,'A#':10,'Bb':10,'B':11,'Cb':11}

TRANSPOSED = {0:'C',1:'Db',2:'D',3:'Eb',4:'E',5:'F',
              6:'F#',7:'G',8:'Ab',9:'A',10:'Bb',11:'B'}

CHORD_REX = re.compile(r'([A-G][#b]?)')

def replace_chord(steps, match):
    return TRANSPOSED[(CHORD_NUM[match.group()] + steps) % 12]

def transpose_string(s, steps):
    return re.sub(CHORD_REX, partial(replace_chord, steps), s)

s = "C Ebm F# Db7"
print transpose_string(s, 4) # -> E Gm Bb F7
Für TRANSPOSED brauchst Du evtl. andere Standards, C# und Gb sind ja auch noch sehr gebräuchlich (im Deutschen auch noch -is und -es). Mußt Du funktionsharmonische Zusammenhänge beachten, gehts nicht mehr so einfach, da die enharmonische Verwechslung u.U. nicht erwünscht ist.

Edit:
Das Bsp. funktioniert nur, wenn Du "reine" Akkordzeichenketten in der obigen Form hast, steht da noch Text dazwischen mit Lettern A-G, werden diese mit umgewandelt. Sind # und b anders kodiert (♯ ♭), müssen die RegEx erweitert oder die Zeichen vorher umgewandelt werden.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Das mit der enharmonischen Verwechslung habe ich schon alles mit einberechnet, sind dann deutlich ein paar Zeilen mehr Code!

Werde mir das aber mit den regulären Ausdrücken mal angucken!

Vielen Dank!
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Code: Alles auswählen

for element in temp:            
            if element in combinations: 
                element = transpose(element, 1)[0] 
Zu was den Index mitführen? Das macht man in Python nicht. (Wenn, dann mit `enumerate`)
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@anogayales:
Mit Erhalt der Funktionsharmonik wirds natürlich schwieriger. Ich würd da ungefähr so vorgehen:
  1. Eingabe "dekodieren". Alle exotischen Zeichen werden in das intern genutzte Alphabet übersetzt.
  2. Mit RegEx alle Treffer in Liste packen, Positionen mit Platzhaltern versehen. "Am Db7 C7" wird zu "%m %7 %7" und ['A', 'Db', 'C']
  3. aus Liste Stufen und Intervalle extrahieren [10, 1, 0] ['4v', '7g']
  4. Stufenliste transponieren, ist jetzt eine einfache map-Konstruktion
  5. Jetzt der schwierige Teil, die neuen Symbole:
    Das ist im Prinzip ein Optimierungsproblem mit der Maßgabe, möglichst wenig ## und bb Akkorde zu erhalten (wer will die schon entziffern) unter Beachtung der Intervalle.
    Ich würd einfach die 5 real möglichen Konstellationen durchgehen (von bb bis ##) und die, mit den wenigsten Doppelvorzeichen gewinnt. Gibt es mehrere Gleichwertige, gewinnt die mit den wenigsten b oder #. Exotische b#-Akkorde wie Fb oder E# würde ich gleich mit unter die Doppelvorzeichenakkorde zählen, da auch nicht erwünscht.
    Ist das Optimum gefunden und bleiben noch Exoten oder bb##-Akkorde übrig, werden diese schließlich enharmonisch verwechselt.
    Zurückgegeben wird eine Liste mit den neuen Akkorden.
  6. Neue Akkorde für Platzhalter einsetzen.
  7. Am Ende evtl. wieder Kodieren, wie gewünscht.
e.) ist nur eine Freitexterklärung, hierfür werden einige Hilfkonstrukte nötig. Vllt. kann man das auch mathematisch eleganter lösen als durch parameterstudienähnliches brute force.

Edit:
Es sind eigentlich nur 2-3 Konstellationen möglich (Je nach Grundton des Ausgangsakkordes und Nähe h-c und e-f). So Sachen wie D### für enh. F sind Unsinn.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

ice2k3 hat geschrieben:

Code: Alles auswählen

for element in temp:            
            if element in combinations: 
                element = transpose(element, 1)[0] 
Zu was den Index mitführen? Das macht man in Python nicht. (Wenn, dann mit `enumerate`)
Das Funktioniert so nicht! temp ist ein ganz normaler String und dann kann man nicht einfach so Wörter rausnehmen, nur einzelne Buchstaben und das bringt bei mir nichts.
BlackJack

@anogayales: Weiter oben hast Du `temp` aber eine Liste von Zeichenketten zugewiesen.
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

Außerdem: selbst wenn es ein normaler String sein sollte -> TypeError: 'str' object does not support item assignment
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@anogayales:
Wenn Du uns etwas mehr Code gönnst, können wir Dir vllt. auch sagen, woran es klemmt. Mit 2 hingeworfenen Zeilen ist uns da nicht geholfen und wenn Du zwischenzeitlich den Typen änderst, liegt das außerhalb des Vermögens unserer Kristallkugel. :wink:

Btw: Wie hast Du denn das mit der Enharmonik gelöst? Du transponierst offensichtlich jedes Element einzeln, da geht doch der funktionsharmonische Kontext verloren? :?:
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Vielen Dank für all euren Input:

Da ich momentan nicht allzu viel Zeit habe an diesem kleinen privaten Projekt zu arbeiten, sollt ich euch nicht wundern, falls ich für ein Weilchen nicht melde.

@jerch:
Ja, du hast recht, mit meiner Methode geht der funktionsharmonische Kontext verloren. Damit kann ich aber leben. Auch werde ich, vorerst, darauf verzichten auf exotische Konstruke wie A#### zu verzichten.

Hauptzweck der Software soll sein, den Songtext zu kopieren und in schnell ohne große Probleme transponieren zu können.

Beispiel:
Folgendes Lied lerne ich gerade:
Abm F#
Sitting by the window
E B
Staring out into the night
C#m Abm F#
Waiting up for the light of day yehh
Abm F#
And the sound of silence
E B
The faintly flaring candle light
C#m
Parting has got me
Abm F#
Around to go insane yehh
Das lied beinhaltet viele Barre Griffe, die einfach unschön sind.
Das ganze in mein Programmier kopiert und um einen Halbton
nach oben transponiert ergiebt:
Am G
Sitting by the window
F C
Staring out into the night
Dm Am G
Waiting up for the light of day yehh
Am G
And the sound of silence
F C
The faintly flaring candle light
Dm
Parting has got me
Am G
Around to go insane yehh
Viel besser zu spielen. Wer interesse an dem Code hat, soll
sich bei mir melden. Es funktioniert mitlerweile das Nötigste.
Bassgrundtöne werden momentan nicht berücksichtigt. Werde ich aber einbauen. Das ganze konnte ich ohne Reguläre Ausdrücke umgehen.
An manchen stellen ist der Code aber nicht sehr pythonic. Naja was solls :P
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Für solche Sachen kann ich Dir das Programm Band-in-a-box empfehlen. Das kann das von Haus aus (neben vielen anderen tollen Sachen wie komplette Band emulieren, Solostimmen erzeugen etc.)

Wegen der Enharmonik hätte ich noch eine Idee:
Man könnte die API so stricken, daß man für einen "strict"-Modus, in dem nicht verwechselt werden darf, nicht die Halbtonschritte angibt, sondern das Intervall:

Code: Alles auswählen

# es wird enharmonisch verwechselt, d.h. das script entscheidet selbst
transpose(string, steps=1)
# strict, keine enharmonische Verwechslung
transpose(string, interval="übermaßige Prime")
Im ersten Fall würde A zu Bb, im zweiten zu A#.
Antworten