Seite 1 von 1
Vorkommen eines Strings zählen, DUplikate ignorieren
Verfasst: Donnerstag 1. Februar 2007, 03:15
von abaum
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?
Verfasst: Donnerstag 1. Februar 2007, 04:25
von EnTeQuAk
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
MfG EnTeQuAk
fehler ausgebessert...
Verfasst: Donnerstag 1. Februar 2007, 06:08
von cracki
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
Verfasst: Donnerstag 1. Februar 2007, 08:41
von 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.
Verfasst: Donnerstag 1. Februar 2007, 13:33
von abaum
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.
Verfasst: Sonntag 4. Februar 2007, 03:24
von Y0Gi
Am Rande: Im (X)HTML-Quelltext müssen XML-Sonderzeichen wie eben auch das Kaufmannsund/Ampersand/& maskiert werden, also: foo?bar=1&baz=2
Verfasst: Dienstag 27. März 2007, 23:13
von abaum
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)
Verfasst: Dienstag 27. März 2007, 23:26
von BlackJack
Da sollte es `set()` im Modul `sets` geben.
Verfasst: Mittwoch 28. März 2007, 08:33
von Sr4l
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.
Verfasst: Mittwoch 28. März 2007, 10:20
von birkenfeld
<nitpick>Es ist nicht nötig, set aufzurufen.</nitpick>