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