Seite 1 von 1
RE Frage
Verfasst: Dienstag 6. Januar 2004, 21:29
von to.ni
Hallo zusammen,
habe heute mit Python "in der Praxis" angefangen und ne Frage zu den REs.
Ich will aus ner HTML-Datei alle Links extrahieren. Theoretisch ganz einfach, da ich das selbe Beispiel auch in nem Buch gefunden habe, aber im Buch wird davon ausgegangen, dass die Links das Format href="..." haben. Links könnten aber auch das Format href = ... haben (also mit leerzeichen, etc.
Ich bin inzwischen soweit:
Code: Alles auswählen
regex = re.compile(r"<a.*?href\s*=\s*[\"|']?.*?[\"|']?.*?>")
result = regex.findall(code)
Das liefert mir den gesamten A-Tag also z.B. <a href="link"> oder <a href = 'link' class = 'test'> oder <a href=link> oder was auch immer.
Aber ich brauche ja nur den HREF-Inhalt. Im Buch wurde das mit runden Klammer gelöst (*.?) - in meinem Beispiel würde das so aussehen:
Code: Alles auswählen
regex = re.compile(r"<a.*?href\s*=\s*[\"|']?(.*?)[\"|']?.*?>")
# ^^^^^
result = regex.findall(code)
Das liefert mir aber eine Liste mit '', '','', etc.
also nicht den gewünschten HREF-Inhalt
Habt ihr ne Idee wie es ausbessern kann?
mfg to.ni
Re: RE Frage
Verfasst: Dienstag 6. Januar 2004, 22:34
von Voges
Hallo!
Vorab: Das | hat in Zeichenmengen keine Sonderbedeutung, also kannst Du es weglassen. [\"'] bedeutet ja schon
" oder '.
Am Beispiel von
<a href=foobar> mal erläutert, was Dein RE macht.
Code: Alles auswählen
<a.*?href\s*= erkennt <a href=
\s* erkennt leeren String
[\"']? erkennt leeren String, logisch
(.*?) erkennt leeren String, das reicht dem Teil-RE schließlich
[\"']? erkennt leeren String, logisch
.*? erkennt foobar
Dem Teil-RE würde der leere String zwar auch reichen,
aber die Folgebedingung hat da was gegen.
> erkennt >
Du hast nach dem Gleichheitszeichen fünf "0 bis"-Bedingungen, und das muss schief gehen, denn jede "0 bis"-Bedingung erkennt vorrangig den leeren String. Und das .*? am Ende ist so wenig spezifisch, dass es alles bekommt.
Mein Vorschlag:
regex = re.compile(r"<a.*?href\s*=\s*([^\s>]+).*?>")
Ich kenne die html-Syntax nicht im Einzelnen. Mein RE funktioniert, wenn der Link kein Leerzeichen enthält (sollte ja wohl so sein) und wenn auf den Link (mit oder ohne Anführungszeichen) ein Leerzeichen oder > folgt. Wenn der Link in Anführungszeichen steht, musst Du die aber anschließend noch entfernen.
Jan
Verfasst: Dienstag 6. Januar 2004, 23:17
von Dookie
Hallo,
hier mal die Regex, die mit und ohne Anführungszeichen funktioniert und die Anführungszeichen nicht mitnimmt:
Code: Alles auswählen
regex = re.compile(r'<a.*?href\s*=\s*"?([^\s">]+).*?>')
Gruß
Dookie
Verfasst: Mittwoch 7. Januar 2004, 20:35
von to.ni
Danke für eure Hilfe,
alles Funktioniert, aber kapiert hab ichs dann doch nur zu (ca.) 80%...
Also ich hab das letzte Beispiel nochmal "Aufgebohrt", damit es auch mit eifnachen ' Funktioniert...
Aber nochmal schauen, was das Teil so macht (für den Lerneffekt):
Code: Alles auswählen
regex = re.compile(r"<a.*?href\s*=\s*[\"']?([^\s\"'>]+).*?>")
Code: Alles auswählen
<a sucht nach <a
.*? es können beliebig viele Zeichen folgen, ein oder null mal
href sucht nach href
\s* es könen beliebige Leerzeichen vorkommen, beliebig oft
= sucht nach =
\s* wieder beliebig viele Leerzeichen
[\"']? " oder ' können einmal oder keinmal vorkommen
( was zwischen den Klammern steht bekomme ich zurück? (unklar)
[^\s\"'>] keine Ahnung... ^ ist mir ein Rätsel...
sonst... es kann vorkommen: ein beliebiges leerzeichen oder " oder ' oder > (falls der TAG aus ist)
+ Das alles muss einmal oder mehrmal vorkommen
) keine Ahnung ;-) siehe oben...
.*? beliebige Zeichen (ein oder 0 mal...)
> findet >
Tja, theoretisch funktioniert alles, aber ganz kapiert hab ichs noch nicht... ( oder ) oder ^
nochmal danke für eure hilfe
mfg
Verfasst: Mittwoch 7. Januar 2004, 20:42
von Dookie
Das was in den Klammern (...) kommt, wird bei findall zurückgegeben.
das ^ bedeutet not, also in dem Beispiel [^\s\"'>] bedeutet: nimm alles was kein Whitespace (Leerzeichen, Tab, Zeilenumbruch, ...), Anführungszeichen (doppelt oder einfach) oder das Grösserzeichen ist.
Das letzte ? kannst auch weglassen.
Gruß
Dookie