Seite 1 von 2
Regex Anfängerproblem,Group gibt nur das erste element zurüc
Verfasst: Samstag 4. Februar 2012, 09:02
von Sico
Hallo,
ich benutze folgenden Code um per Regex <description> auszulesen:
Code: Alles auswählen
string = re.search("<description>(.*)</description>",html)
print string.groups(1)
Jetzt zeigt er mir natürlich nur das erste description an...wie kann ich mir auch noch alle anderen ausgeben lassen welche in html vorhanden sind.
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Samstag 4. Februar 2012, 10:03
von deets
Gar nicht. Stattdessen solltest du einen HTML/XML-Parser verwenden, wie zB lxml oder zumindest ElementTree aus der stdlib. Dann kannst du so schoene Sachen wie "findall" machen.
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Samstag 4. Februar 2012, 10:32
von problembär
Sico hat geschrieben:Code: Alles auswählen
string = re.search("<description>(.*)</description>",html)
Nicht gut wegen Gier. Besser:
Code: Alles auswählen
string = re.search("<description>([^>]*)<\/description>", html)
Wenn das ganze html in einem String ist, mußt Du den natürlich splitten:
Code: Alles auswählen
html = html.split("\n")
for i in html:
i = i.rstrip("\n")
matchobj = re.search("<description>([^>]*)<\/description>", i)
if matchobj:
print matchobj.groups()
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Samstag 4. Februar 2012, 11:45
von deets
@problembaer
Ein schoenes Beispiel, warum regulaere ausdruecke zur Verarbeitung von HTML ungeeignet sind, und dein Kreuzzug gegen richtige Ratschlaege bestenfalls Verwirrung, wenn nich gar Schaden anrichtet.
Code: Alles auswählen
html = """
<html>
<body>
<description>foo</description>
<description>
bar
</description>
<description><b>baz</b></description>
</body>
</html>
"""
import re
for i in html.split("\n"):
i = i.rstrip("\n")
matchobj = re.search("<description>([^>]*)<\/description>", i)
if matchobj:
print matchobj.groups()
from xml.etree.ElementTree import fromstring
doc = fromstring(html)
for d in doc.findall(".//description"):
print d.text
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Samstag 4. Februar 2012, 13:56
von pillmuncher
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Samstag 4. Februar 2012, 14:39
von sma
Also man kann schon XML mit REs parsen.
Die Antwort auf das eigentlich Problem ist IMHO, "findall" bzw. "finditer" statt "search". Mit "search" findet man nur das erste Vorkommen eines regulären Ausdrucks in einem String, nicht alle. Außerdem sollte man bedenken, dass REs normalerweise greedy sind, d.h. den längsten möglichen String finden. Will man das nicht, sollte man hinter dem * (oder +) ein ? einfügen.
Dieser RE-basierte Parser kann übrigens XML korrekt zerlegen. Ich habe mir Attribute geschenkt, die könnte ich prinzipiell ebenfalls verarbeiten, nur dann hätte ich den Code nicht in 5min zusammenschreiben können:
Code: Alles auswählen
def sax_parse(s):
def unquote(t): return t.replace("<", "<").replace("&", "&")
for m in re.finditer(r"</\s*(.+?)\s*>|<\s*(.+?)\s*/>|<\s*(.+?)\s*>|([^<]+|<)", s.strip()):
end, empty, start, text = m.groups()
if start:
yield sax_parse.START, start
elif end:
yield sax_parse.END, end
elif empty:
yield sax_parse.START, empty
yield sax_parse.END, empty
else:
yield sax_parse.TEXT, unquote(text)
Damit könnte ich jetzt nach "description"-Tags suchen. Man könnte noch prüfen, ob das XML überhaupt wohlgeformt ist. Doch das mache ich gleich. Man müsste wohl auch unquote noch ausbauen. Das überlasse ich dem Leser genau wie das Behandeln von XML-Dokumenten, die nicht als UTF-8 vorliegen.
Dieses Beispiel kann ich jetzt korrekt verarbeiten:
Code: Alles auswählen
html = """
< html >
<body>
<description>foo</description>
<description>
bar
baz
</description>
<description><b>baz</b></description>
</body>
</html>"""
for e, t in sax_parse(html):
print e, `t`
Es darf aber gerne noch etwas komfortabler sein. Ich baue mir schnell ein Objektmodell, damit ich XML-Elemente als Exemplare der Klasse `Elem` repräsentieren kann, die jeweils einen Namen und Kinder haben und zwei Attribute, in denen ich die Textknoten sammle.
Code: Alles auswählen
class Elem:
def __init__(self, name):
self.name, self.children, self.text, self.tail = name, [], "", ""
def __str__(self):
return "<%s>%s%s</%s>%s" % (self.name, self.text, "".join(str(c) for c in self.children), self.name, self.tail)
Und habe dafür einen Parser, der mir mit Hilfe meines ersten Parsers nun eine Hierarchie von Elem-Objekten erzeugt:
Code: Alles auswählen
def elem_parse(s):
stack = []
for t, e in sax_parse(s):
if t == sax_parse.START:
stack.append(Elem(e))
if t == sax_parse.END:
if stack and stack[-1].name == e:
elem = stack.pop()
if stack: stack[-1].children.append(elem)
else: return elem
else: raise ValueError("wrong </%s>" % e)
if t == sax_parse.TEXT:
if stack:
if stack[-1].children: stack[-1].children[-1].tail += e
else: stack[-1].text += e
else: raise ValueError("no root")
raise ValueError("stuff after end")
Dieser Parser prüft dann nun auch, ob das XML-Dokument wohlgeformt ist.
Fügen wir noch folgende Methode zu `Elem` hinzu:
Code: Alles auswählen
def find_all(self, name):
if name == self.name:
yield self
else:
for c in self.children:
for e in c.find_all(name):
yield e
Nun kann ich bequem nach allen description-`Elem`s suchen, nur mit regulären Ausdrücken:
Code: Alles auswählen
for e in elem_parse(html).find_all("description"):
print e
Stefan
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Samstag 4. Februar 2012, 15:08
von deets
@sma
Schön zu sehen, dass reguläre Ausdrücke einen kleinen Anteil in der korrekten Verarbeitung von *ML spielen können.
Geht aber ein bisschen am Punkt hier vorbei, oder nicht? Natürlich ist es jedem freigestellt, seine Standardimplementation eines Parsers selbst zu bauen. Oder seine eigene Sprache. Aber ich für meinen Teil nehme vorlieb mit Python & seiner standart Bibliothek

Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Samstag 4. Februar 2012, 16:43
von sma
deets hat geschrieben:Schön zu sehen, dass reguläre Ausdrücke einen kleinen Anteil in der korrekten Verarbeitung von *ML spielen können.
Hätte ich die Ironie durch einen

verdeutlichen müssen?
Stefan
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Samstag 4. Februar 2012, 18:18
von deets
Ja

zumindest wenn ich sowas auf meinem iPhone lese - da ist die Schrift sonst zu
Klein

und ich behaupte, unser problembär nimmt das als beispiel , wie man ohne "modulgefrickel" weiter kommt...
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Samstag 4. Februar 2012, 18:50
von sma
deets hat geschrieben:Ja

zumindest wenn ich sowas auf meinem iPhone lese - da ist die Schrift sonst zu
Klein

und ich behaupte, unser problembär nimmt das als beispiel , wie man ohne "modulgefrickel" weiter kommt...
Also ersteres ist ja wohl ganz klar ein Problem des Forums und nicht meines Beitrags

Ich würde mir auch eine mobile Form wünschen, wo ich - sei es per App oder angepasster Website - bequem vom Handy aus lesen und antworten kann. Dann würden meine Postings auch nicht so lang werden. Außer, ich könnte sie Siri diktieren.
Das den anderen Punkt angeht: Ich sehe einen großen Wert darin, nicht nur Module anwenden zu können, sondern auch zu wissen, wie man den Code - wenigstens prinzipiell - selbst schreiben würde. Das ist nicht nur eine gute Übung, sondern man lernt den Aufwand der Erstellung eines guten Moduls erst schätzen - oder erkennt schlechte Module. Außerdem hilft es, die Algorithmen zu kennen, wenn man mehr als nur Python anwenden können will. Weil mir z.B. Element-Tree als API gut gefiel, habe ich mir das unter iOS basierend auf dem mitgelieferten NSXMLParser selbst gebaut. Da da wollte ich nicht mit Modulen (bzw. fremden statischen Bibliotheken) frickeln. Und nein, bevor jemand fragt, libxml2 einbinden ist auch nicht wirklich einfacher, weil das ein C-API und umständlich aus Objective-C heraus zu benutzen ist.
Stefan
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Samstag 4. Februar 2012, 19:22
von problembär
deets hat geschrieben:@problembaer
Ein schoenes Beispiel, warum regulaere ausdruecke zur Verarbeitung von HTML ungeeignet sind, und dein Kreuzzug gegen richtige Ratschlaege bestenfalls Verwirrung, wenn nich gar Schaden anrichtet.
Kreuzzug ist, wenn man eine bestimmte Auffassung verlangt und alle anderen bekämpft, weil man glaubt, schon im Besitz der letzten Wahrheit zu sein.
Ich dagegen trete für Code-Toleranz ein und für die Freiheit, das zu schreiben, was man möchte, egal ob es der Obrigkeit genehm ist oder nicht. Das ist das Gegenteil von Kreuzzug. Du verwechselst die Seiten, auf denen wir stehen.
Wenn also jemand HTML mit RegEx parsen möchte, sag' ich, "laß' ihn doch" und helfe ihm so gut ich kann dabei, daß es technisch auch klappt.
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Samstag 4. Februar 2012, 20:47
von Hyperion
problembär hat geschrieben:
Ich dagegen trete für Code-Toleranz ein und für die Freiheit, das zu schreiben, was man möchte, egal ob es der Obrigkeit genehm ist oder nicht.
Eigentlich schön formuliert - nur dass es hier keine "Obrigkeit" gibt; ich bin ihr zumindest noch nicht begegnet

Ansonsten stimmen Dir hier sicherlich die meisten zu, dass man coden darf, was man will und wie man will, aber...
problembär hat geschrieben:
Wenn also jemand HTML mit RegEx parsen möchte, sag' ich, "laß' ihn doch" und helfe ihm so gut ich kann dabei, daß es technisch auch klappt.
... es gibt eben gute und schlechte Hilfe. Wenn jemand über eine x spurige Straße gehen will und das Konzept des Druckknopfs für die Fußgängerampel nicht kennt, dann erkläre ich ihm dieses und sage nicht "Ich sag Bescheid, wenn links frei ist!"

Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Sonntag 5. Februar 2012, 01:05
von deets
problembär hat geschrieben:
Kreuzzug ist, wenn man eine bestimmte Auffassung verlangt und alle anderen bekämpft, weil man glaubt, schon im Besitz der letzten Wahrheit zu sein.
Ich dagegen trete für Code-Toleranz ein und für die Freiheit, das zu schreiben, was man möchte, egal ob es der Obrigkeit genehm ist oder nicht. Das ist das Gegenteil von Kreuzzug. Du verwechselst die Seiten, auf denen wir stehen.
Wenn also jemand HTML mit RegEx parsen möchte, sag' ich, "laß' ihn doch" und helfe ihm so gut ich kann dabei, daß es technisch auch klappt.
Wie ich ja schnell gezeigt habe, ist es mit dem "technischen klappen" deiner Hilfe nicht so weit her. Du hast also dem OP eine Baerendienst erwiesen (wie nicht anders zu erwarten...).
Und wenn jemand dabei ist, sich in den Fuss zu schiessen, aber der Abzug klemmt - dann bist du offensichtlich derjenige, der im die Waffe klariert, damit er das Blutbad anrichten kann. Und das mit dem religioesen Eifer der Kreuzfahrer....
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Sonntag 5. Februar 2012, 11:34
von sma
Ich denke, beide Seiten haben recht. Aus eigenen Fehlern zu lernen ist häufig der Weg, der besser funktioniert. Ein (gut gemeintes) "das macht man so nicht" ist dann weniger konstruktiv als der direkte Weg zur eigenen Erkenntnis. Oder um Bild zu bleiben, führe den Fragesteller ruhig auf den Mittelstreifen, warte bis er dort nicht mehr weiterkommt, und dann hilf ihm zurück und über die Brücke anstatt sofort zu sagen, "man geht da nicht rüber, aber in 3km Entfernung ist eine Brücke".
Ich bin da eher bei Problembär als das ich denke, dass man jeden Fragesteller zwangsbeglücken muss. Ich würde schon erwähnen, dass ich (bei meinem aktuellen Kenntnisstand des Problems und meinem Vorwissen) meine, dass es einen besseren Weg gibt, aber auch die möglichst direkte Antwort geben (findall statt search).
Und wäre es z.B. notwendig, aus großen Mengen XML, wo ich das Format sehr genau kenne, sehr schnell etwas zu extrahieren, dann würde ich schon zu REs greifen und nicht das mitgelieferte XML-API von Python benutzen. Das ist einfach pragmatisch. Will ich's bequem haben und sichergehen, dass alle Randfälle von XML abgedeckt sind, nehme ich den XML-Parser. Die Entscheidung ist aber in beiden Fällen nicht absolut.
Stefan
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Sonntag 5. Februar 2012, 13:13
von Hyperion
sma hat geschrieben:Oder um Bild zu bleiben, führe den Fragesteller ruhig auf den Mittelstreifen, warte bis er dort nicht mehr weiterkommt, und dann hilf ihm zurück und über die Brücke anstatt sofort zu sagen, "man geht da nicht rüber, aber in 3km Entfernung ist eine Brücke".
Hm... Du setzt dabei voraus, dass der OP aus Fehlern lernt; meine Erfahrungen als Nachhilfelehrer haben mir immer gezeigt, dass das bei den meisten dort nicht der Fall war, sondern man diese Leute direkt auf den "richtigen" Weg leiten musste. Sobald sie diesen einmal verstanden hatten, war das Problem damit gegessen. Ok, man kann natürlich einwerfen, dass Schüler / Studenten, die Nachhilfe benötigen, ggf. nicht repräsentativ sind

Ich denke vielleicht ist der Mittelweg der richtige: Man sagt dem Fragesteller, dass es eine Brücke gibt, das der sicherere Weg ist und ggf. wieso sein Weg nicht so gut ist. Sobald er das explizit erfahren hat, kann ihm ja jeder noch auf seinem eingeschlagegen Weg weiterhelfen.
Dabei sollte man auch nie google und die stillen Mitleser vergessen - die wollen ja auch sicher ans Ziel kommen

Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Sonntag 5. Februar 2012, 20:39
von snafu
Man kann auch einfach antworten: "Die Lösung deines speziellen Problems geht so-und-so. Wenn du das intensiver betreibst, würde ich jedoch zu Modul xyz raten - das ist auf Dauer viel einfacher." Oder, wenn schon einiges an Code da ist: "Guck mal, wie komplex das ist. Da blickt ja kaum einer durch. Schau mal, mit Modul xyz bekomme ich das in 2 Zeilen hin..."
Ich glaube einfach, es ist didaktisch sinnvoller, jemandem erst seine Frage möglichst zu beantworten und ihm dann einen alternativen Weg anzubieten, anstatt direkt mit dem erhobenen Zeigefinger zu kommen, unter der strengen Annahme, dass ein Anfänger niemals-nie überhaupt falschen Code sehen darf und man ihn bloß vor diesem Unheil bewahren muss. problembär ist natürlich der krasse Gegenpol von dieser Ansicht. Dies halte ich ebenfalls für wenig zielführend. Und sma hat ja zum Glück bereits gesagt, dass man seine Antwort ruhig mit einem Augenzwinkern betrachten sollte - puh...! ^^
//edit: Und natürlich hat deets anschaulich dargelegt, warum es in "ernsthaften" Anwendungsfällen besser ist, etwas robustes fertiges zu verwenden. Prinzipiell könnte man aber trotzdem zunächst den regulären Ausdruck für einen simplen Fall zeigen, danach auf mögliche Fallstricke hinweisen und sozusagen als Fazit dann die Nutzung eines speziellen Moduls empfehlen. Das soll jetzt natürlich keine direkte Handlungsanweisung sein. Ich kann sma's Einwände aber halt schon irgendwo verstehen...
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Sonntag 5. Februar 2012, 20:49
von BlackJack
@snafu: Wenn Du den Leuten die Frage beantwortest, wie sie dynamische Namen mit angehängten Nummern erzeugt oder wie man etwas mit ``global`` oder `eval()` „löst”, dann muss man aber auch damit leben, dass die das dann tatsächlich *machen* und sich nicht um die saubere Alternative scheren.
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Sonntag 5. Februar 2012, 20:58
von snafu
@BlackJack: Nun ja. Wenn man zusätzlich argumentiert, *warum* Listen besser als das Durchnummerieren von Variablen sind, kann man vielleicht auch einfach mit seiner Überzeugungskraft wirken. Wenn ein Anfänger unbedingt bei seinem Codestil bleiben will, dann kann man eh nicht viel machen. Wieso sollte man auch? Er würde sich jedenfalls die von ihm gewünschte Antwort schon von irgendwo her holen.
Es gibt ja IMHO 2 Sorten bzw Reaktionsarten von Anfängern: Die einen nehmen das dankbar an und ermuntern indirekt zu weiteren Ratschlägen und die anderen haben so oder so keinen Bock drauf - sie wollen einfach nur, dass es irgendwie compil...äh...funktioniert.

Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Sonntag 5. Februar 2012, 21:03
von Hyperion
Finden wir den einen Konsens, wenn man sagt, dass ein Anfänger vor allem aus Unkenntnis der sinnvollen Möglichkeiten einen eher ungünstigen Weg einschlägt, bei dem es dann hakt?
Wenn ja, ist es doch eher hilfreich ihm diesen Weg aufzuzeigen; ich nehme mich da nicht aus und habe durch solche Hinweise hier viel gelernt.
Ob man jemanden davon abhalten sollte, einen ungünstigen Weg zu beschreiten... da bin ich ein wenig unschlüssig; wer sich ins Knie schießen will, soll das ruhig tun. Aber ich denke man darf ihn dann ruhig drauf hinweisen und im Idealfall begründen, wieso das ein schlechter Weg ist. Zumal eben auch anderen Leute einen solchen Thread ggf. finden und die sollten dann zumindest die Chance haben, den richtigen Weg einzuschlagen oder, sofern dieser nicht eindeutig bestimmbar ist, zumindest einen Überblick über die Alternativen und deren Vor- bzw. Nachteile zu erhalten.
Re: Regex Anfängerproblem,Group gibt nur das erste element z
Verfasst: Sonntag 5. Februar 2012, 21:09
von snafu
Ich spreche natürlich davon, mögliche Gefahren von "anfängerfreundlichen" Code (im Sinne von: mit den Mitteln einer begrenzten Kenntnis des Sprachumfangs) auch direkt im selben Post zu erwähnen, sodass jemand, der 1 Jahr später den Thread findet, dies nicht erst auf Seite 3 erfährt. Das sollte aber eigentlich auch klar sein, denke ich.