Bestimmte Stelle auslesen

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
NicNac
User
Beiträge: 19
Registriert: Sonntag 17. Juni 2012, 12:14

Hallo ihr lieben.

ich habe mir eine kleine Funktion geschrieben die mir einen bestimmten quelltext einer seite in eine datei speichert. nur speichert er natürlich bestimmte html tags mit ab. diese wollte ich mittels regex nun auschliessen aber irgendwie will er das nicht bzw bringt mir immer nur das er nichts findet. mein source an dieses stelle sieht wie folgt aus:

Code: Alles auswählen

beispiel = re.findall('<span>(.*)</span>', fobj)
print(beispiel)
Normalerweise müsste er mir doch jetzt alles was zwischen (.*) steht ausgeben und in "beispiel" speichern oder?

Bin für ejde Hilfe dankbar
deets

Tut er doch:

Code: Alles auswählen

import re
from cStringIO import StringIO

fobj = StringIO("""<span>a</span><span>b</span>""")

beispiel = re.findall('<span>(.*)</span>', fobj.read())
print(beispiel)
Aber lass mich raten: fobj ist kein File-Objekt (also voellig falsch benannt...), und deine Eingabe umfasst mehrere Zeilen, und eigentlich willst du "a", "b" haben und nicht das andere span dazwischen?

Dann ist es Zeit statt regulaeren Ausdruecken mal nen HTML-Parser zu benutzen. Ich empfehle BeautifulSoup, weils pures Python ist und einfach zu installieren. lxml kann sowas aber auch sehr gut.
NicNac
User
Beiträge: 19
Registriert: Sonntag 17. Juni 2012, 12:14

Doch "fobj" ist ein File Objekt

er speichert mir ja den Quelltext den ich haben will in ein File.
Danach will ich aus diesem File genau das was zB zwischen:
<span> und </span> steht.

was sich auch natürlich über mehrere Zeilen erstreckt weil is ja ein html dokument. ungefähr so:

Code: Alles auswählen

<span>
blablabla
    xxxxxxxx
      aaaaaa
</span>
Und dann genau das dazwischen
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Der Punkt trifft normalerweise auf alle Zeichen bis den Zeilenumbruch zu. Kombiniert mit dem Stern, bekommst du nur den Inhalt zwischen den beiden äußersten Tags. Klar kann man beides umgehen (re.DOTALL und weniger gierige Suche), aber schlussendlich ist es wesentlich einfacher lxml.clean oder so einzusetzen.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@NicNac: Statt sich mit HTML + regex zu quälen, wäre es nicht einfacher, den persönlichen Masochismus im SM-Studio auszuleben und derweil HTML mittels eines ordentlichen HTML-Parsers zu verarbeiten? Also Separation of Concerns, gewissermaßen. BeautifulSoup wurde ja schon genannt.
In specifications, Murphy's Law supersedes Ohm's.
NicNac
User
Beiträge: 19
Registriert: Sonntag 17. Juni 2012, 12:14

Ja ihr habt ja recht mit dem ordentlichen HTML Parser. Ich hab das ganze mal mit lxml versucht umzusetzen. Aber dort titt jetzt das Problem auf das ich nicht alle tags auschliessen kann um den reinen Text zu speichern der Code sieht jetzt wie folgt aus:

Code: Alles auswählen

    cleaner = Cleaner(page_structure=False, links=True, forms=True)
    
    cleaner.remove_tags = ['p']
    print cleaner.clean_html(html)

Wenn ich aber den "p" tag entferne was auch funktioniert anscheinend. mach er mir dafür wo immer auch her ein "div" tag obwohl es garnich existiert?!?

Ich will ja nur den reinen txt von mehreren Zeilen speichern ohne tags das kann ja nich so schwer sein lol das macht mich ganz wahnsinnig.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Schau doch mal in die Doku! Da findest Du die Methode `text_content` für HTML-Elemente; und die sollte genau das tun, was Du willst.

Willst Du alles, so rufst Du diese auf dem Wurzelelement auf, willst Du nur spezielle Sub-Bäume, so musst Du diese eben zuvor selektieren (per `xpath` oder `iter`) und dann jeweils auf den Knoten aufrufen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
NicNac
User
Beiträge: 19
Registriert: Sonntag 17. Juni 2012, 12:14

Danke für eure Hilfe jetzt hat alles wunderbar geklappt. Ich würde aber noch gern den Thread hier nutzen bevor ich einen neuen mach für eine letze abschliessende Frage.

Am Ende meines Programms führe ich wie "execfile('myFile.py') ein Script aus was im Projektordner liegt. Aaaaaber
das macht er mir nicht, er führt alles einwandfrei aus ohne Fehler nur auch ohne mein exec. Alles was vorher geschieht das auslesen, ausgeben bestimmter stelle ect funzt.
Was ich kurios finde ist, wenn ich ein neues File mache und dort lediglich den execfile reinpacke zum testen funzt alles einwandfrei nur in meinem programm am ende nicht? Ich finde dazu auch keine referenz zum nachlesen

Vielen lieben Dank
BlackJack

@NicNac: Meine Glaskugel sagt, dass Du dann irgend etwas falsch machst in dem Quelltext der vor der besagten Zeile steht.
NicNac
User
Beiträge: 19
Registriert: Sonntag 17. Juni 2012, 12:14

@Black

Etwas falsch obwohl es richtig läuft? Und alles Ordnungsgemäß ausgeführt wird? Mein Script endet wie folgt:

Code: Alles auswählen

#print new_list  # test only
        
    clean_text = "".join(new_list)
    print clean_text
    cScript = open('beispiel.py','w')
    cScript.write(clean_text)
    cScript.close
    
    exScript = 'beispiel.py'
    execfile(exScript)
BlackJack

@NicNac: Wenn das erzeugte Skript kürzer als der Puffer für Dateioperationen ist, wird es nicht geschrieben bevor die Datei geschlossen wurde. Du müsstest sie halt schliessen. Die `close`-Methode einfach nur zu referenzieren reicht nicht — Du musst sie auch *aufrufen*.

Wobei ich mich frage warum Du in einer so dynamischen Programmiersprache wie Python Quelltext generieren musst und warum der in einer Datei landen muss. Das sieht mir nach einem „code smell” aus.

Die Namen `cScript` und `exScript` sehen auch komisch aus. Sie halten sich in der Schreibweise nicht an PEP 8 -- Style Guide for Python Code und keiner der beiden Namen steht direkt für ein Skript. Das eine ist ein Dateiobjekt und das andere ein Dateiname. Wobei man den Namen nicht zweimal literal im Programm stehen haben sollte. Wenn man den ändern möchte, sollte man das nur an einer Stelle tun müssen. `new_list` scheint auch ein Name zu sein, über den nicht nachgedacht wurde.
Antworten