quelltext von x bis y in eine variable speichern

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
dirtylion
User
Beiträge: 19
Registriert: Sonntag 13. März 2011, 13:33

hi,
sorry die noob frage..
ich beschäftige mich erst seit wenigen tagen mit python..

womit parse ich am besten einen teil von einem quelltext..von stelle x bis stelle y.

ich habs mit re.findall getestet aber bei mehreren lines geht das leider nicht :(


von <h2>Mittwoch, 16.03.2011</h2> bis <div class="s_body_end"></div> soll er alles speichern

vielen dank !
BlackJack

@dirtylion: Für HTML sollte man einen HTML-Parser verwenden und nicht den Quelltext per `re` durchsuchen. `lxml.html` oder `BeautyfulSoup` sind die beiden gängigen Module für solche Aufgaben.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich würde im Zusammenhang mit HTML-Dokumenten nicht von Quelltext sprechen (selbst wenn der Browser das so nennt: "Seitenquelle anzeigen" sagt mein Chrome) und ich meinem Vorredner bzgl. lxml oder der wunderschönen Suppe anschließen. Aber wenn's unbedingt sein muss, geht das natürlich schon mit regulären Ausdrücken:

Code: Alles auswählen

start = "<h2>Mittwoch, 16.03.2011</h2>"
stop = "<div class="s_body_end"></div>"

m = re.find("(?s)" + start + ".*" + stop, source)
if m: print m.group()
Und das Problem ist sogar so einfach, dass es auch ganz ohne reguläre Ausdrücke funktioniert:

Code: Alles auswählen

try:
    i = source.index(start)
    j = source.index(stop, i)
    print source[i:j+len(stop)]
except ValueError:
    pass
Stefan

Update: DOTALL ergänzt.
Zuletzt geändert von sma am Sonntag 13. März 2011, 18:00, insgesamt 1-mal geändert.
dirtylion
User
Beiträge: 19
Registriert: Sonntag 13. März 2011, 13:33

danke !!
dirtylion
User
Beiträge: 19
Registriert: Sonntag 13. März 2011, 13:33

leider funktionier dein tipp nicht :(
http://www.python-forum.de/pastebin.php?mode=view&s=170

start = "<h2>"
stop = "body_end>"

m = re.findall(start + ".*" + stop, data)
print m

er gibt nix aus.. ich denke mal weil es mehrere lines sind befindet sich start und stop in einer line geht es..
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Du suchst nach dem DOTALL-Flag: http://docs.python.org/library/re.html#re.DOTALL
dirtylion
User
Beiträge: 19
Registriert: Sonntag 13. März 2011, 13:33

danke mit der DOTALL (re.S) flag bin ich wieder gekommen :)

was ich jetzt nicht verstehe warum ich nicht die variable info wieder als source nutzen kann..

nun habe ich ein problem was ich nicht verstehe:

import urllib, re

url = "http://www.serienwiki.de"
data = urllib.urlopen(url).read()

info = re.findall('<h2>Sonntag,.*?2011</h2>(.*?)<div class="s_body_end"></div>', data, re.S)
print info
done = re.findall("<h2>(.*?)</h2>", info)
print done

output:

root@dm8000:~# python test.py
['\n\t \t\t\t\t\n<div class="s_body_start"></div><div class="s_body_body"><table width="710" border="0" cellpadding="0" cellspacing="0"><tr class="sender" onmouseover="this.style.background=\'#BBB7B7\';" onmouseout="this.style.background=\'#FFFFFF\';"><td align="right"><b>20:15</b></td><td valign="bottom"><img src="/images/tvlogos/sat1.gif" title="SAT.1" alt="" /></td><td><a href="/serien/NCIS/">Navy CIS</a></td><td width="30" align="center"></td><td align="right"><b>8x05</b>&nbsp;&nbsp;&nbsp;</td><td><a href="/episoden/NCIS/8x5-Feld-der-Alptraeume.html">Feld der Alptr&auml;ume</a></td><td align="left" width="85"> </td></tr>\n<tr class="sender" onmouseover="this.style.background=\'#BBB7B7\';" onmouseout="this.style.background=\'#FFFFFF\';"><td align="right"><b>21:15</b></td><td valign="bottom"><img src="/images/tvlogos/sat1.gif" title="SAT.1" alt="" /></td><td><a href="/serien/the-mentalist/">The Mentalist</a></td><td width="30" align="center"></td><td align="right"><b>3x05</b>&nbsp;&nbsp;&nbsp;</td><td><a href="/episoden/the-mentalist/3x5-Schnell-wie-der-Wind.html">Schnell wie der Wind</a></td><td align="left" width="85"> </td></tr>\n<tr class="sender" onmouseover="this.style.background=\'#BBB7B7\';" onmouseout="this.style.background=\'#FFFFFF\';"><td align="right"><b>22:10</b></td><td valign="bottom"><img src="/images/tvlogos/sat1.gif" title="SAT.1" alt="" /></td><td><a href="/serien/hawaii-5-0/">Hawaii Five-0</a></td><td width="30" align="center"></td><td align="right"><b>1x01</b>&nbsp;&nbsp;&nbsp;</td><td><a href="/episoden/hawaii-5-0/1x1-Aloha-Steve-McGarrett.html">Aloha, Steve McGarrett</a></td><td align="left" width="85"> <span style="color: #3390DD; font-weight: bold; font-size: 80%; text-transform:uppercase;">Serienstart</span> </td></tr>\n<tr class="sender" onmouseover="this.style.background=\'#BBB7B7\';" onmouseout="this.style.background=\'#FFFFFF\';"><td align="right"><b>23:10</b></td><td valign="bottom"><img src="/images/tvlogos/sat1.gif" title="SAT.1" alt="" /></td><td><a href="/serien/hawaii-5-0/">Hawaii Five-0</a></td><td width="30" align="center"></td><td align="right"><b>1x02</b>&nbsp;&nbsp;&nbsp;</td><td><a href="/episoden/hawaii-5-0/1x2-Ein-Sicherheitsrisiko.html">Ein Sicherheitsrisiko</a></td><td align="left" width="85"> </td></tr>\n</table>\n</div>\n']
Traceback (most recent call last):
File "test.py", line 8, in <module>
done = re.findall("<h2>(.*?)</h2>", info)
File "/usr/lib/python2.6/re.py", line 177, in findall
return _compile(pattern, flags).findall(string)
TypeError: expected string or buffer

falls nun fragen aufkommen was ich überhaupt versuche ich wollte mir mit einem script serien anzeigen lassen die zum aktuellen tag laufen.. das ganze als script für enigma2 (dreambox).
BlackJack

@dirtylion: Die Fehlermeldung ist doch wohl deutlich: `info` ist weder eine Zeichenkette noch ein `buffer`. Das ist eben das was `re.findall()` erwartet. Welchen Typ `info` hat, sieht man ziemlich deutlich an der ``print``-Ausgabe. Wenn Du das nicht siehst, dann solltest Du erst einmal ein Python-Tutorial durcharbeiten, bevor Du an dem Programm weiter schreibst.

Und Informationen mit regulären Ausdrücken aus Webseiten heraus zu holen ist ziemlich unsauber. Ich würde hier auf jeden Fall einen HTML-Parser verwenden.

Edit: Ich habe gerade mal auf die Seite geschaut -- diese Daten scheinen auch als RSS-Feed angeboten zu werden. Das ist noch sicherer als sich das aus einer Webseite zu kratzen.

Edit2: So einfach kann das gehen: http://paste.pocoo.org/show/352998/
dirtylion
User
Beiträge: 19
Registriert: Sonntag 13. März 2011, 13:33

ok.. vielen dank ich versuche es dann mal mir dem rss-feed
mit den HTML-Parser ist mir zu kompliziert.. da blicke ich nicht ganz durch.

ich würde mich aber über einen lösungsweg mit dem re.findall freuen :)

weil so gehe ich dem problem aus dem weg..

hiermit bekomme ich alles schön angezeigt:

import urllib, re, time

url = "http://www.serienwiki.de"
data = urllib.urlopen(url).read()

series = re.findall("<b>(.*?)</b></td>.*?title=.(.*?). alt.*?href=.*?>(.*?)</a>.*?right.><b>(.*?)</b>.*?href=.*?>(.*?)</a>", data)

for serie in series:

print serie[0], serie[1], serie[2], serie[3], serie[4]

output:

root@dm8000:~# python test.py
20:15 SAT.1 Navy CIS 8x05 Feld der Alptr&auml;ume
21:15 SAT.1 The Mentalist 3x05 Schnell wie der Wind
22:10 SAT.1 Hawaii Five-0 1x01 Aloha, Steve McGarrett
23:10 SAT.1 Hawaii Five-0 1x02 Ein Sicherheitsrisiko
01:15 SAT.1 Worst Week 1x10 Die K&ouml;chin und die Tauben
01:35 SAT.1 Worst Week 1x11 Das Cello und die Kekse
01:55 SAT.1 Worst Week 1x12 Die Schwiegermutter und das Dingsda
20:00 Schweiz 2 Desperate Housewives 7x11 Attent&auml;ter
20:13 13th Street Shattered 1x01 Die S&uuml;nden der V&auml;ter
20:15 ProSieben Fringe - Grenzf&auml;lle des FBI 3x08 Entrada
20:15 SuperRTL Glee 1x10 Balladen
20:15 ORF1 Desperate Housewives 7x11 Attent&auml;ter
20:15 Sky Cinema Hits Supernatural 5x21 Das Ende ist nah
20:15 SAT.1 Der letzte Bulle 2x01 Mord auf Distanz
20:50 Schweiz 2 Glee 1x10 Balladen
20:55 Sky Cinema Hits Supernatural 5x22 Schwanenlied
21:05 13th Street Shattered 1x02 Verheiratet
21:15 SAT.1 Danni Lowinski 2x01 Um die Wurst
21:15 ProSieben Vampire Diaries 2x08 Rose
21:15 RTL Rach, der Restauranttester 5x07 Zum wei&szlig;en Stein, Wismar
22:00 Fox Channel West Wing 7x03 Grenzg&auml;nger
22:15 ProSieben Supernatural 4x21 Wenn der Damm bricht
22:40 ORF1 Nurse Jackie 1x10 Hand anlegen
23:55 3Sat In Treatment - Der Therapeut 2x04 Walter - Donnerstag, 17 Uhr (1. Woche)
20:15 RTL CSI: Miami 8x15 Miami, wir haben ein Problem!
20:15 Sixx Life Unexpected 1x11 St&uuml;rmische Nacht
20:15 ProSieben Die Simpsons 21x15 Der gestohlene Kuss
21:10 ProSieben Two And A Half Men 7x15 Charlies Engel
22:10 ProSieben Scrubs - Die Anf&auml;nger 9x11 Unsere H&ouml;llenwoche
22:15 RTL Psych 3x14 Wahrere L&uuml;gen
22:40 ProSieben Scrubs - Die Anf&auml;nger 9x12 Unsere Fahrk&uuml;nste
23:05 ProSieben Scrubs - Die Anf&auml;nger 9x13 Unser Dankesch&ouml;n
23:10 RTL Law & Order 20x11 Links und rechts der B&uuml;rgerrechte
20:15 RTLCrime Hustle - Unehrlich w&auml;hrt am l&auml;ngsten 6x01 Und ewig lockt die Chefinspektorin
20:15 TNT Serie Boardwalk Empire 1x07 Vergangenheit und Zukunft
20:15 ProSieben Desperate Housewives 7x11 Attent&auml;ter
20:15 RTL II Stargate: Universe 2x01 Feindlicher &Uuml;bergriff - Teil 3 (aka. Intervention)
20:15 VOX Law & Order: Special Victims Unit 11x11 1000 Frauen
21:10 RTL II Stargate: Universe 2x02 Nachwirkungen
22:15 RTL II True Blood 1x01 Strange Love
23:10 RTL II True Blood 1x02 Blut geleckt

mir fehlt nur der wochentag davor.. das ist mein eigentliches problem..
dirtylion
User
Beiträge: 19
Registriert: Sonntag 13. März 2011, 13:33

beim rss-feed werden leider nur die täglichen serien angezeigt nicht für mehrere tage :(
d.h ich muss weiter testen.. :)
BlackJack

@dirtylion: Du gehst dem Problem eines komplizierten HTML-Parsers durch komplizierte und unlesbare reguläre Ausdrücke aus dem Weg, die eine nicht besonders robuste Lösung sind!? ;-)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ja das kommt meist davon wenn jemand eine Lösung mit ``re`` postet. Da kann man dann noch so viel Warnen und es als schlecht bezeichnen, diese Lösung wird in 90% aller Fälle dann genommen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
dirtylion
User
Beiträge: 19
Registriert: Sonntag 13. März 2011, 13:33

für einen html parser weg wäre ich auch dankbar :)
BlackJack

Bitteschön:

Code: Alles auswählen

import lxml.html


def main():
    # doc = lxml.html.parse('test.html').getroot()
    doc = lxml.html.parse('http://www.serienwiki.de/').getroot()
    
    for day_node in doc.cssselect('div.tabber div.tabbertab'):
        day_string = day_node.find('h2').text
        for row in day_node.cssselect('div.s_body_body tr.sender'):
            (time_node,
             station_node,
             series_node,
             dummy,
             episode_node,
             title_node,
             remark_node) = row.findall('td')
            
            time = time_node.text_content()
            station = station_node.find('img').get('title')
            series = series_node.text_content()
            episode = episode_node.text_content().strip()
            title = title_node.text_content()
            remark = remark_node.text_content()
            
            print day_string, time, station, series, episode, title, remark


if __name__ == '__main__':
    main()
Die Information lässt sich anhand der CSS-Selektoren recht gut ansteuern.
dirtylion
User
Beiträge: 19
Registriert: Sonntag 13. März 2011, 13:33

danke nun muss ich nur das modul auf die dreambox bekommen bzw. installieren :) dann teste ich es..
Antworten