Klasse zum Songtext suchen

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
dodo47
User
Beiträge: 5
Registriert: Dienstag 12. Dezember 2006, 15:34

Dienstag 12. Dezember 2006, 17:50

Hallo,
ich hab eine Klasse geschrieben die Songtexte bei http://www.leoslyrics.com/ sucht und diese dann ausgibt.

Code: Alles auswählen

import urllib
import re

class Lyrics:
    def __init__(self):

        self.list_reg   = re.compile(r"<td>[.|\s]*<font .*>[.|\s]*<a href=\".*\">(.*)</a>[.|\s]*</font>[.|\s]*</td>[.|\s]*<td>[.|\s]*<font .*>[.|\s]*<a href=\"(.*)\"><b>(.*)</b></a>[.|\s]*</font>[.|\s]*</td>")
        self.result_reg = re.compile(r"<p>[.|\s]*Found <b>(\d*)</b> results\.[.|\s]*</p>")
        self.sid_reg    = re.compile(";jsessionid=.*\\?")
    
    def search(self, artist = "", song = "", album = ""):

        return_list = []
        self.url_list = []

        artist = urllib.quote(artist)  
        song   = urllib.quote(song)  
        album  = urllib.quote(album)
        url    = "http://www.leoslyrics.com/advanced.php?artistmode=0&artist="+artist+"&albummode=0&album="+album+"&songmode=0&song="+song+"&mode=0"
        page   = urllib.urlopen(url)
        page   = page.read()

        results = int(re.findall(self.result_reg, page)[0])

        if results%40 == 0:
            pages = results/40
        else:
            pages = results/40+1

        self.big_list = re.findall(self.list_reg, page)

        n = 2
        while n < pages:
                page = urllib.urlopen(url+"&page="+str(n))
                page = page.read()
                self.big_list.append(re.findall(self.list_reg, page))
                n = n+1

        for n in self.big_list:
            return_list.append((n[0], n[2]))
            self.url_list.append("http://www.leoslyrics.com"+re.sub(self.sid_reg, "?", n[1]))
        return_list = tuple(return_list)
        self.url_list = tuple(self.url_list)

        return return_list

    def get_text(self, number):
        page = urllib.urlopen(self.url_list[number]).read()

        page = page.replace('\r\n', '\r')
        page = page.replace('\r\n', '\r')
        new = []
        for zeile in page.split("\r"):
            zeile = zeile.strip()
            if not zeile == "":
                new.append(zeile.strip())

        lyric = []
        first = True
        for n in range(0, len(new)):
            if new[n].startswith("<br />"):
                if first:
                    lyric.append(self.__finish__(new[n-1]))
                    lyric.append(self.__finish__(new[n]))
                    first = False
                else:
                    lyric.append(self.__finish__(new[n]))
        return lyric

    def __finish__(self, string):
        string = string.replace("\r", "")
        string = string.replace("'", "'")
        string = string.replace(""", "\"")
        string = string.replace("<br />", "")
        return string
Benutzt wir das ganze wie folgt:

Code: Alles auswählen

suche = Lyrics()
ergebnis = suche.search(artist = "irgendwas")
songtext = suche.get_text(index_zahl_von_ergebnis)
Findet ihr das nützlich?
Über Verbesserungsvorschläge würde ich mich freuen.
Gruß
dodo47
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Freitag 15. Dezember 2006, 12:42

Mir ist nur aufgefallen: __finish__ finde ich nicht gerade einen tollen Methodennamen. Es gibt keine Grund für die Unterstriche, sie verwirren nur.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Freitag 15. Dezember 2006, 16:29

Habs nur schnell überflogen. Verbesserungsvorschläge: kein __finish__, das sollte man nur für interne python Funktionen verwenden, _finish ist da besser. Und ein maximales Zeilenlimit von 80 Zeichen ist grunsätzlich eine gute Idee.
TUFKAB – the user formerly known as blackbird
Benutzeravatar
SigMA
User
Beiträge: 181
Registriert: Sonntag 4. April 2004, 13:27
Wohnort: Freiburg
Kontaktdaten:

Freitag 15. Dezember 2006, 17:29

Code: Alles auswählen

n = n+1
schöner:

Code: Alles auswählen

n += 1
Hab auch nur kurz drüber geschaut. Aber ich bin mir sicher, dass ich nochmal auf den Quellcode zugreifen werde =)

SigMA
Zuletzt geändert von SigMA am Samstag 16. Dezember 2006, 22:33, insgesamt 1-mal geändert.
Leichtdio.de - Das Kreativ-Blog
http://www.leichtdio.de
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Freitag 15. Dezember 2006, 20:37

@dodo47:
Willkommen im Forum.

Erstmal Coole Sache. Kann man gebrauchen.

Kritik:
Zeile 8-10 ist über EOL80.


Zeile 15: `self.url_list = []`. Warum wird das Klassenattribut nicht schon im Konstruktor bekannt gemacht? Also alles mit `self.` am Anfang ist Global in der Klasse ansprechbar. Da finde ich, das man Attribute nicht verstreut einführen sollte sondern Zentral und das am besten im Konstruktor. Daher würde ich `self.url_list = []` unter dem Atribut `self.sid_reg` in der `__init__`-Methode schrieben.

Zeile 31: Siehe Zeile 15.

Zeile 20: Über EOL80 und sonst auch nicht PEP8 Konform.

Ich würde dir empfehlen PEP8 zu lesen.
Z.B:

Code: Alles auswählen

 page = urllib.urlopen(url+"&page="+str(n))  
gehört

Code: Alles auswählen

 page = urllib.urlopen(url + "&page=" + str(n))

Code: Alles auswählen

 if results%40 == 0:
            pages = results/40
        else:
            pages = results/40+1
gehört

Code: Alles auswählen

 if results % 40 == 0:
            pages = results / 40
        else:
            pages = results / 40 + 1
etc.


PEP8: http://www.python.org/dev/peps/pep-0008/
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Freitag 15. Dezember 2006, 20:39

SigMA hat geschrieben:

Code: Alles auswählen

n = n+1
schöner:

Code: Alles auswählen

n +=1
[...]
Leerzeichen nicht vergessen.

Code: Alles auswählen

n += 1
dodo47
User
Beiträge: 5
Registriert: Dienstag 12. Dezember 2006, 15:34

Montag 18. Dezember 2006, 14:59

Danke für die Antworten.
Hab mal das zu beantstandene verbessert und die Leerzeichen eingefügt, nur wie bekomme ich diese langen Zeilen mit den regexp denn unter 80 Zeichen?

Will das ganze jetzt so erweitern das einmal gesuchte Songtexte in einer sqlite Datenbank gespeichert werden, nur da hänge ich ein wenig bei der Kodierung der Querys, da mann ja oft die gleichen Lieder hört und so sich und der Songtextseite Traffic erspart.

BTW:
Kennt ihr andere Seiten wo man Songtexte bekommt OHNE sich dafür anmelden zu müßen?
Python 47
User
Beiträge: 574
Registriert: Samstag 17. September 2005, 21:04

Montag 18. Dezember 2006, 16:38

Hallo Dodo 47,

die langen Zeilen bekommst du so weg:
[wiki]Lange Zeilen im Sourcecode[/wiki]
und ne Seite wo man Songtexte ohne Anmeldung bekommt hab ich auch:
http://lyrics.songtext.name/
mfg

Thomas :-)
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Dienstag 19. Dezember 2006, 00:54

Die Zeilen 17-22 sind ebenfalls nicht PEP-konform, weil diese Tabulator-Fakes bei Änderungen irgendwann nicht mehr gepflegt und dann ein unschönes Hindernis werden.

Für reguläre Ausdrücke gibt es auch eine Verbose-Syntax, mit der man sie mehrzeilig gestalten und Kommentare einfügen kann.


Insgesamt mal wieder bemerkenswert, dass hier generell viel über Aussehen und Struktur des Codes nachgedacht wird und weniger um die eigentliche Funktion (wobei letztere aber in aller Regel bei diesen Codesnippet-Threads in Ordnung und nicht weiter diskutierbar ist). Aber das gefällt mir irgendwie an der Python-Gemeinde und grenzt *sehr stark* gegenüber vielen Java- und PHP-Schmieden ab.
Antworten