Problem mit Regex (re)

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
maxwell
User
Beiträge: 69
Registriert: Samstag 11. Juli 2009, 15:36
Wohnort: am Fernsehturm in B.

Hallo Foristen,
ich habe ein Problem das sich wie folgt darstellt.
Ich möchte eine html Seite parsen. Dargestellt wird eine Tabelle deren Inhalt es zu holen gilt. An sich kein Problem - jedoch ist oberhalb der
Tabelle ein Basiswert angegeben ist. Diesen möchte ich gerne zu jedem Match hinzufügen.

Ausgangslage:
--------------
Basiswert: 00,90

[col(0)] [col(n)]
WERT1 WERT2 ...

Ergebnis:
---------
[(WERT1, WERT2), (WERT(N), ...), ...]

Sollergebnis:
------------
[(00,90, WERT1, WERT2), (WERT(N), ...), ...]

Wie kann man das abbilden?
Gr. chris
be or not to be
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Man parst nicht HTML mit regulären Ausdrücken, da es einem mehr Probleme bereitet als gleich mit einem passenderem Modul (wie lxml) loszulegen.
maxwell
User
Beiträge: 69
Registriert: Samstag 11. Juli 2009, 15:36
Wohnort: am Fernsehturm in B.

Hi webspider,
erstmal Danke für Deine Mühe. Ich habe aber nun immer noch das gleiche Problem und möchte meine Arbeit erstmal nicht über den Haufen werfen.
Ist aus meiner Sicht erstmal nicht zielführend. ;)
be or not to be
BlackJack

@maxwell: Welches Problem hast Du denn jetzt genau? Weisst Du nicht wie Du den Basiswert aus dem HTML-Quelltext bekommst? Oder wie man mit Tupeln umgeht?
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Die andere Frage ist, inwieweit die gewählte Datenstruktur praktisch im Umgang ist. Ich fände es zum Beispiel einfacher eine eigene Klasse anzulegen mit Basiswert und Tabelleninhalt als Attributen und für jede geparste Tabelle ein solches Objekt zu erstellen. Insbesondere wenn später darauf zugegriffen werden muss, wird diese Vorgehensweise einem die Arbeit um einiges erleichtern.
Ich […] möchte meine Arbeit erstmal nicht über den Haufen werfen.
Klar willst du das nicht. Aber wenn die nötigen Änderungen verhältnismäßig gering sind, dir das Refactoring den Code übersichtlicher und besser macht und du dann auch noch was dazulernst was den guten Umgang mit Python angeht, lohnt es sich IMO mehr als sich auf Workarounds zu verlassen.
maxwell
User
Beiträge: 69
Registriert: Samstag 11. Juli 2009, 15:36
Wohnort: am Fernsehturm in B.

@BlackJack:

Der Basiswert kommt nur einmal vor. Er steht außerhalb (oberhalb) der Tabelle. Die Tabelle Parsen ist nicht das Problem.

Code: Alles auswählen

import re

isin_wkn = r"""
	<td\s+class="first">\s*						# ISIN
		<span\s+title="([\w]*)"\s+class="nowrap">\s*
			<a\s*href=.*?</a>\s*
		</span>\s*
		<br>\s*									# WKN
		<span\s+title="([\w]*)"\s+class="nowrap">.*?"""

basiswert = r"""
	<b>Basiswert:</b>
		.*?\(Aktuell:\s*([.0-9]*)\s*\|"""

n = re.compile(isin_wkn, re.X|re.S)
print re.findall(html_file, n)
Ich erhalte - wie gewünscht - pro Zeile der Tabelle ein Tuple aus ISIN & WKN)
Ich benötige aber zusätzlich pro Zeile den Basiswert.

Beispiel:
[ (Basiswert, ISIN1, WKN1), (Basiswert, ISIN2, WKN2), ... ]

@webspider:
Das was Du schreibst ist absolut richtig. Aber, es geht hier nur um das abgreifen der Informationen.
Den Rest - alle Operationen - erledige ich dann in der Datenbank. Es erfolgt keine Verarbeitung im Programm selbst. Wie gesagt ich gebe Dir Recht nur kann ich mich nicht 5 Wochen in eine Masterlösung knien. Du weißt was ich meine?
be or not to be
deets

Code: Alles auswählen

from itertools import cycle
startwert = "foo"
werte = range(20)

print zip(cycle([startwert]), werte)
Und das ist die simple, aber Vorwissen benoetigende Loesung. Ein simples

Code: Alles auswählen

res = []
for wert in findall(whatever):
   res.append((startwert, ) + tuple(wert))

oder Spielarten davon - das sollte dir doch auch eingefallen sein, oder?
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

deets: statt cycle([startwert]) geht auch repeat(startwert) (repeat kommt auch aus dem itertools-Modul).
deets

@derdon

Ah, danke, ich wusste nur es gab *irgendwas* zum repitieren, und bin beim erstbesten stehen geblieben. itertools ist immer wieder ein ganz besonderes Modul.
deets

maxwell hat geschrieben: Das was Du schreibst ist absolut richtig. Aber, es geht hier nur um das abgreifen der Informationen.
Den Rest - alle Operationen - erledige ich dann in der Datenbank. Es erfolgt keine Verarbeitung im Programm selbst. Wie gesagt ich gebe Dir Recht nur kann ich mich nicht 5 Wochen in eine Masterlösung knien. Du weißt was ich meine?
Das ist eine Fehleinschaetzung. Es geht nicht 5 Wochen in irgendwas zu investieren. Wenn ich mir deinen Code anschaue, dann sind das ziemlich ausbaldowerte regulaere Ausdruecke - die aber am Ende in etwas wie BeautifulSoup oder lxml dank xpath oder aehnlichem sehr schnell und wesentlich robuster ersetzt werden koennen.

Use the right tool for the job - dann braucht's auch keine 5 wochen.
maxwell
User
Beiträge: 69
Registriert: Samstag 11. Juli 2009, 15:36
Wohnort: am Fernsehturm in B.

Das ist eine Fehleinschaetzung. Es geht nicht 5 Wochen in irgendwas zu investieren. Wenn ich mir deinen Code anschaue, dann sind das ziemlich ausbaldowerte regulaere Ausdruecke - die aber am Ende in etwas wie BeautifulSoup oder lxml dank xpath oder aehnlichem sehr schnell und wesentlich robuster ersetzt werden koennen.
Wenn Du Dich da mal nicht irrst. :wink:
be or not to be
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

maxwell hat geschrieben: Wenn Du Dich da mal nicht irrst. :wink:
Also Dein Code-Schnipsel oben sieht schon mal nach übelster Frickelei aus - das wäre mit einem HTML-Parser def. einfacher und robuster gegangen. (Und je nach Kenntnisstand auch schneller ;-) )
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
deets

Tue ich bestimmt nicht. Aber *ich* bin nicht derjenige, der davon zu ueberzeugen ist - sondern du. Sieht allerdings nicht danach aus, als ob du das ausprobieren moechtest, ob dem so ist.
maxwell
User
Beiträge: 69
Registriert: Samstag 11. Juli 2009, 15:36
Wohnort: am Fernsehturm in B.

Irgendwie fühle ich mich hier total misverstanden. :twisted:

Natürlich bin ich davon überzeugt das es auch anders geht. Und überzeugen muss mich deshalb ja keiner. Ich habe nur nicht die Zeit mich momentan damit zu beschäftigen. Lass mich nochmal festhalten - mir geht es um die Daten - nicht darum wie die Daten am gescheitesten u. besten geholt werden.

Irgendwie habe ich auch geahnt - bevor ich den Thread überhaupt verfasste - dass gleich alle wieder aus den Ecken strömen und meinen "Hey das geht anders viel besser ...". :mrgreen:

Ja mai - dann gebt doch bitte mal ein Beisoiel ... :roll:

Übrigens habe ich zwischenzeitlich dann doch mit Beautiful Soup experimentiert. Irgendwie aber auch nicht so erfrischend wie es mir suggeriert wurde.

mhhhh ...
be or not to be
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Gib Du uns doch mal ein Beispiel des HTML-Codes und an welche Daten Du ran willst - dann kann man Dir auch ein Beispiel geben!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
deets

maxwell hat geschrieben: Irgendwie habe ich auch geahnt - bevor ich den Thread überhaupt verfasste - dass gleich alle wieder aus den Ecken strömen und meinen "Hey das geht anders viel besser ...". :mrgreen:
Ja, das ist schon ganz schoen schlimm - da fragt man um Hilfe in einem kostenlosen, oeffentlichen Forum. Und dann haben die Leute, die da fuer Umme ihre Hilfe anbieten, auch noch *eigene* Ideen und Vorstellungen, anstatt einfach nur stumpf das zu tun, was man ihnen aufgetragen hat...

Kannst dir gar nicht vorstellen, wie sehr ich mit dir fuehle...
maxwell hat geschrieben:
Ja mai - dann gebt doch bitte mal ein Beisoiel ... :roll:

Übrigens habe ich zwischenzeitlich dann doch mit Beautiful Soup experimentiert. Irgendwie aber auch nicht so erfrischend wie es mir suggeriert wurde.

mhhhh ...
Ja mai, dann gib doch mal nen Beispiel von deinem HTML, und was du so zusammengebastelt hast mit BS.
maxwell
User
Beiträge: 69
Registriert: Samstag 11. Juli 2009, 15:36
Wohnort: am Fernsehturm in B.

Hi Hyperion, deets,

erstmal danke für das Feedback.

Hier der beispielhafte HTML-Code der Tabelle:

Code: Alles auswählen

<table class="cardTable">
	<colgroup>
		<col width="17" />
		<col width="50" />
        <col width="50" />
	</colgroup>
	<tr>
		<th rowspan="2">&nbsp;</th>
		<th rowspan="2" class="nowrap  first">
			<span title="ISIN"><a href="...">ISIN</a></span>
			<br>
			<span title="WKN"><a href="...">WKN</a></span>
		</th>                      
		<th rowspan="2" class="nowrap ">
			<span title="Geld">Geld</span>
			<br>
			<span title="Brief">Brief</span>
		</th>
		<th rowspan="2" class="nowrap ">
			<span title="Datum | Zeit">Datum Zeit</span>
			<br>
            <span title="...">Börsenplatz</a></span>
        </th>
	</tr>
	<tr>
		<td class="first">
			<span title="DE000GS86N87" class="nowrap">
				<a href="...">DE000GS86N87</a>
            </span>
			<br>
            <span title="GS86N8" class="nowrap">GS86N8</span>
		</td>
		<td >
			<span class="nowrap">1,56</span>
			<br>
            <span title="1 : 1" class="nowrap">1 : 1</span>
		</td>
		<td >
            <span class="nowrap">20.02.12&nbsp;&nbsp;&nbsp;13:09</span>
            <br>
			<span title="Frankfurt (Scoach)" class="nowrap">Frankfurt (Sc..</span>
		</td>
	</tr>
	......
</table>
@deets:
Du verstehst das schon wieder falsch. Ich habe nichts gegen Anregungen. Never, niemals ... :D
be or not to be
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Beschwer dich aber nicht hinterher bei uns wenn deine regulären Ausdrücke nach minimalen Änderungen des HTML-Quellcodes nicht mehr funktionieren :P
deets

Finde ich deutlich simpler & klarer als dein rex-gefummel. Und hat keine 5 Wochen gedauert.

Code: Alles auswählen

from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup(html)

wkn = soup.find(title='WKN').find("a").text
isin = soup.find(title='ISIN').find("a").text

print wkn, isin
Deinen Tabellenfall konnte ich nicht reproduzieren - das was du schreibst ("Aktuell:" usw) kommt in deinem HTML nicht vor.
maxwell
User
Beiträge: 69
Registriert: Samstag 11. Juli 2009, 15:36
Wohnort: am Fernsehturm in B.

Hallo deets,
danke für Dein Feedback. Ich habe mich noch mal mit BSoup beschäftigt.

Code: Alles auswählen

from BeautifulSoup import BeautifulSoup
bs = BeautifulSoup(raw)

t = bs.find('table', {'class':'cardTable'})

hdr = t.findNext('tr')
for h in hdr.findAll('span'):
	print h['title']

rows = hdr.findAllNext('tr')

for r in rows:
	for s in r.findAllNext('span'):
		print s.text
Problem ist nur, dass in der letzten Spalte der letzte Zeile der Tabelle der Spalteninhalt im Attribut ('title') steht.
Es gibt "span"s die jedoch nicht über dieses Attribut verfügen.
Naja man könnte dann über nen exeception Block abfangen und im Zweifel den text nehmen ...

Gr. Chris
be or not to be
Antworten