Vorkommen eines Strings zählen, DUplikate ignorieren

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
abaum
User
Beiträge: 18
Registriert: Freitag 12. Januar 2007, 21:53
Kontaktdaten:

Hallo,
zur Zeit stehe ich vor folgendem Problem: ich habe den Quellcode einer Webseite, in dem überall Links mit dem selben Aufbau verteilt sind:

Code: Alles auswählen

<a href="pdf_navi.asp?y=2007&m=01&d=31&f=35&ext=.pdf" target="PDF_Navi">35</a>
Manche Links kommen auch mehrmals vor. Jetzt möchte ich gerne wissen, wie viele einzigartige Links es gibt, d. h. auf wie viele einzelne Seiten verlinkt wird. string.count() fällt ja leider aus...
Was ist eurer Ansicht nach die "pythonischste" Problemlösung?
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Also treffen kannst du die Links mit einer regular expression.

Zählen kannst du, indem du erstmal versuchst alle gleichartigen Links zu finden. Das geht mit der Funktion 're.findall'.

Code: Alles auswählen


import re

# die Regex ist nicht funktionstüchtig! :)
link_re = re.compile('^< href="(?P<link>.*)"(.*)?$(?uism)')


txt = '''<a href="pdf_navi.asp?y=2007&m=01&d=31&f=35&ext=.pdf" target="PDF_Navi">35</a>
<a href="pdf_navi.asp?y=2007&m=01&d=31&f=35&ext=.pdf" target="PDF_Navi">35</a>
<a href="pdf_navi.asp?y=2007&m=01&d=31&f=35&ext=.pdf" target="PDF_Navi">35</a>'''

# Bsp...
for line in txt.split('\n'):
    c = 0
    match = link_re.match(line)
    if match is not None:
        if len(link_re.findall(txt)) == 1:
            c += 1

print 'Anzahl Links %d' % c
Ich muss noch darauf hinweisen, das obiges nicht funktioniert, da ich immo nicht in der Lage bin eine ordentliche Regex aufzubauen...
(müde etc...)

Aber so in dem Dreh sollte es funktionieren.

Wenn nicht... meine Müdigkeit war schuld :D

MfG EnTeQuAk

fehler ausgebessert...
cracki
User
Beiträge: 72
Registriert: Montag 25. Dezember 2006, 05:01

erst mit einer regex alle links finden, die fuer dich interessant sind.

dann machst du for "len(set(liste))"

edit: der code:

Code: Alles auswählen

linkrex = re.compile(r"pdf_navi\.asp\?y=(\d+)&m=(\d+)&d=(\d+)&f=(\d+)&ext=\.pdf")

allelinks = linkrex.findall(deineseite)
einzigartig = set(allelinks)

print "einzigartige links:", len(einzigartig)
for url in einzigartig:
    print "%3d" % allelinks.count(url), url
...meh...
BlackJack

Statt regulärem Ausdruck könnte man auch BeautifulSoup benutzen, um die Links zu finden. Das ist sicherer, falls sich das Format mal irgendwann ändern sollte oder wenn auskommentierte Links in den HTML-Daten vorkommen.
abaum
User
Beiträge: 18
Registriert: Freitag 12. Januar 2007, 21:53
Kontaktdaten:

Vielen Dank, cracki! Du hast mich vor der quasi unmöglichen Aufgabe bewahrt, selber eine regex zusammenzuwurschteln *einfachnichtcheck* ;)
Ich habe sie noch etwas angepasst, da die Parameter y, m und d bereits kenne.
@BlackJack: Wenn sich das Format ändert, muss ich eh große Teile der Applikation anpassen, da fällt das auch nicht mehr ins Gewicht. Abgesehen davon finde ich BeautifulSoup sehr interessant und werde es sicherlich im Auge behalten.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Am Rande: Im (X)HTML-Quelltext müssen XML-Sonderzeichen wie eben auch das Kaufmannsund/Ampersand/& maskiert werden, also: foo?bar=1&baz=2
abaum
User
Beiträge: 18
Registriert: Freitag 12. Januar 2007, 21:53
Kontaktdaten:

cracki hat geschrieben:erst mit einer regex alle links finden, die fuer dich interessant sind.
dann machst du for "len(set(liste))"
Jetzt wollte ich das Programm auf einem anderen Rechner ausführen, auf dem allerdings nur Python 2.3 installiert ist. set() wurde aber erts mit 2.4 eingeführt. Wie löse ich dieses Problem am elegantesten? (Python updaten ist keine Option, es handelt sich um Shared Hosting)
BlackJack

Da sollte es `set()` im Modul `sets` geben.
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

Code: Alles auswählen

try: 
    set() 
except NameError: 
    import sets 
    set = sets.Set 
    frozenset = sets.ImmutableSet
So ist sichergestellt das es immer geht. Bei alten Python Modulen importiert er es über sets bei neuen nimmt er die build -in

Ehre dem dem sie gebührt ^^, den Code hat Leonidas mal geschreiben, wenn ich mich richtig errinnere.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

<nitpick>Es ist nicht nötig, set aufzurufen.</nitpick>
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Antworten