html parser

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.
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Samstag 2. Mai 2009, 15:38

Sehr geehrtes Python Forum,

Code: Alles auswählen

import sys
text = """<b>buffer</b>
<form>
lalala
lululu
</form>
buffer
<form>
buffer
</form>
alla"""

istrue = False

liste = []

form1 = ""
for el in xrange(len(text)):
    if istrue:
        if text[el] == "<":
            if text[el + 1] == "/" and text[el + 2] == "f" and text[el + 3] == "o" and text[el + 4] == "r" \
                        and text[el + 5] == "m" and text[el + 6] == ">":
                            form1 = form1 + "</form>"
                            istrue = False
                            liste.append(form1)
                            form1 = ""
                            continue
                            
        form1 = form1 + text[el]
    if text[el] == "<":
        if text[el + 1] == "f" and text[el + 2] == "o" and text[el + 3] == "r" and text[el + 4] == "m":
            istrue = True
            form1 = form1 + "<"
Das ist der hässlichste Code den ich je geschrieben habe - ich weiß.
Aber er funktioniert. :roll:

Da dieser Code so schwer lesbar ist schreibe ich mal die Ausgabe hin:

Code: Alles auswählen

>>> liste
['<form>\nlalala\nlululu\n</form>', '<form>\nbuffer\n</form>']
Ich brauche etwas, wie oben, dass den Ihnalt einzelner htmltags auslesen kann, ich habe es ja schon geschafft, aber da der Code so ekelhaft ist frage ich euch mal ob das irgentwie schöner ( Mal vom Pep8 abgesehen ) machen kann.

Geht das?

MfG INFACT

EDIT: Code aufgebessert...
Zuletzt geändert von INFACT am Samstag 2. Mai 2009, 16:08, insgesamt 3-mal geändert.
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Benutzeravatar
cofi
Moderator
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Samstag 2. Mai 2009, 15:54

Hmm .. Phraser ... nette Wortschöpfung ;) Was du suchst ist ein HTML - PARSER.

Beautiful Soup, lxml.html, ... da gibts viele mit denen du glücklicher wirst.
BlackJack

Samstag 2. Mai 2009, 15:54

Argh! Ja das geht schöner -- in dem man einen HTML-Parser nimmt. So heisst das übrigens auch: Parser und nicht Phraser. ;-)

Ansonsten gibt's auch so schöne Methode wie `str.find()`, die man sich nicht mit aufwändigen Schleifen selber basteln muss.
vario
User
Beiträge: 4
Registriert: Freitag 24. Oktober 2008, 15:43

Samstag 2. Mai 2009, 15:55

Wie wäre es mit regular expressions? Damit könntest Du nach

<deintag> text text text ... </deintag>

direkt suchen, dir die einzelne Teile ausgeben lassen, etc. Schau mal hier:

http://www.amk.ca/python/howto/regex/ und hier http://docs.python.org/library/re.html

Ansonsten gibt es für HTML bestimmt auch schon etwas.
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Samstag 2. Mai 2009, 16:03

Etwas in der Art?

Code: Alles auswählen

>>> l = re.compile("<form>*</form>")
>>> l.findall(text)
[]
Das Sternchen würde, dann alles bedeuten können...

CAUTION: der Code klappt nicht
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Samstag 2. Mai 2009, 16:05

Code: Alles auswählen

>>> l = re.compile("<form>[\d\s\w]</form>")
>>> l.findall(text)
Der Code würde klappen wenn zwischen <form> und </form> nur 1 char wäre...
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Samstag 2. Mai 2009, 16:15

HTML mit Regular Expressions zu parsen ist auch sinnlos, was du suchst ist ein Parser. Wie schon die Vorposter gemeint haben.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Samstag 2. Mai 2009, 16:55

INFACT hat geschrieben:

Code: Alles auswählen

if text[el + 1] == "/" and text[el + 2] == "f" and text[el + 3] == "o" and text[el + 4] == "r" \
     and text[el + 5] == "m" and text[el + 6] == ">":
Btw die `text[:6]`-Notation kennst du?

Code: Alles auswählen

if text[:6] == '<form>':
    ....
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Samstag 2. Mai 2009, 16:58

Oder das:

Code: Alles auswählen

text.startswith('<form>')
Hast du eigentlich jemals in Pythontutorial durchgemacht?
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Samstag 2. Mai 2009, 17:10

Ein einfacher re zum Parsen von HTML:

Code: Alles auswählen

In [16]: a = re.compile(r"(<(?P<tag>[^/]+?)>(?P<inhalt>.*)</(?P=tag)>)+", re.MULTILINE)

In [17]: c = a.search(text)

In [18]: c
Out[18]: <_sre.SRE_Match object at 0x9f97660>

In [19]: c.groups()
Out[19]: ('<b>buffer</b>', 'b', 'buffer')
Strings kann man wie Listen behandeln, siehe Slice Notation (zb in "A Byte of Python" nachschlagen, du verstehst ja kein Englisch). Du könntest auch den Text mit Methoden wie startswith(), find usw in immer kleinere in (logische) Einheiten zerteilen.

Übringens: Du bist ziemlich hartnäckig. Dein Code wird sieht auch deutlich besser aus als noch vor zwei Monaten, auch wenn du bestimmte (doch sehr grundlegende Dinge) wie zb eben dieses "slicen" nicht kennst und dir die Erfahrung im Herangang an Probleme fehlt. Wenn du jetzt noch dein Englisch verbesserst, damit du zb die offizielle Dokumentation lesen kannst, kommt das schon mit der Zeit.

EDIT: Hab MULTILINE mit DOTALL verwechselt:

Code: Alles auswählen

In [31]: a = re.compile(r"(<(?P<tag>[^/]+?)>(?P<inhalt>.*?)</(?P=tag)>)+", re.DOTALL)

In [32]: for m in a.finditer(text):
    print m.groups()
   ....:     
   ....:     
('<b>buffer</b>', 'b', 'buffer')
('<form>\nlalala\nlululu\n</form>', 'form', '\nlalala\nlululu\n')
('<form>\nbuffer\n</form>', 'form', '\nbuffer\n')
lunar

Samstag 2. Mai 2009, 18:20

Code: Alles auswählen

from __future__ import print_function, division

import lxml.html

text = """\
<b>buffer</b>
<form>
lalala
lululu
</form>
buffer
<form>
buffer
</form>
alla"""

tree = lxml.html.fromstring(text)
for form in tree.findall('form'):
    print(form.text_content().strip())
Man parst HTML nicht mir regulären Ausdrücken!
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Samstag 2. Mai 2009, 18:33

Man parst HTML nicht mir regulären Ausdrücken!
In richtigem Code natürlich nicht. Mir scheint aber das INFACT nicht ernsthaft HTML parsen will, sondern sich nur ein wenig an dererlei Dingen versuchen will. Einen (sehr kleinen und rudimentären) HTML Parser zu erstellen, der sehr ausdrucksschwach und fehleranfällig ist, ist relativ leicht und mag eine nette Übung sein. Sein ursprünglichen Code zeigt imho doch schon, das er nicht wirklich Seiten damit auslesen will.
lunar

Samstag 2. Mai 2009, 18:38

Ich denke, du urteilst da etwas vorschnell, was sagt dir, dass das nicht einfach nur Beispielcode ist?
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Samstag 2. Mai 2009, 19:04

Nichts, aber es wurde ja schon auf richtige Parser hingewiesen, und darauf, das man RE's dafür nicht nehmen sollte - würde er bei dem ernsthaftem Parsen von HTML trotz Hinweisen auf entsprechende Parser zwanghaft etwas mit regulären Ausdrücken zusammenbauen wollen, wäre er schlicht selbst schuld, denn man erkennt schnell, wie einfach einem die Parser das Parsen machen, Suchfunktion hier im Forum reicht ja schon. Hätte er dabei Hilfe gebraucht, hätte er dann nochmal fragen können. Aber gut, ich hätte "Bei ernsthaften Angelegenheiten: Kein HTML mit RE parsen" nochmal mit Nachdruck unter mein Posting setzen können.
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Samstag 2. Mai 2009, 21:14

Okay, ich kann lesen... :o
Ich habe jetzt 500 mal versucht lxml zu installieren...
... diesmal hat es geklappt, aber wenn ich das auführe tritt jedes mal ein Fehler auf, in io.py, http://paste.pocoo.org/show/115446/

Code: Alles auswählen

>>> import lxml.html

Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    import lxml.html
  File "C:\Python\Lib\site-packages\lxml\html\__init__.py", line 12, in <module>
    from lxml import etree
  File "lxml.etree.pyx", line 34, in lxml.etree (src/lxml/lxml.etree.c:144634)
  File "C:\Python\lib\io.py", line 502
    n = (readahead.find(b"\n") + 1) or len(readahead)
                            ^
SyntaxError: invalid syntax
Ich habe keine Ahnung was da stattdessen stehen soll...
weiß jemand was ich machen muss, damit das klappt
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Antworten