Verständnisfrage zu folgendem Code:

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
Rumpel
User
Beiträge: 9
Registriert: Dienstag 5. August 2014, 08:32

Hallo Jungs,

ich komme von Java und bin mit Python noch nicht ganz so sicher, aber mühsam nährt sich das Eichhörnchen :)
Ich habe jedenfalls mit Python und BeautifulSoup (echt große klasse!) ein kleines Skript geschrieben, welches mir
aus den Spielplan-Daten des Berliner Ensembles ein paar Infos rausholt. Das sieht dann so aus:

Code: Alles auswählen

from bs4 import BeautifulSoup
from requests import get

url = "http://www.berliner-ensemble.de/spielplan"

soup = BeautifulSoup(get(url).content)

iframes = [i.find('iframe') for i in soup('td', {'class': 'Bleft'})]

for i in iframes:
    iframe = BeautifulSoup(get(i.attrs['src']).content)
    columns = [i.text for i in iframe.findAll('td')]
    print columns
Bei diesem Code hat mir freundlicherweise jemand von Stackoverflow geholfen und nun tut er auch, was er tun soll.
Meine Frage ist nun folgende: Bzgl. der Sntax verstehe ich noch nicht ganz wie er in dieser Zeile vorgeht:

Code: Alles auswählen

iframes = [i.find('iframe') for i in soup('td', {'class': 'Bleft'})]
Was bedeutet i.find('iframe') ? Was ist in diesem Falle i ? Ist das der Iterator der Liste iframe? Gibt es dazu ein Tutorial?

Vielen Dank Jan
BlackJack

@Rumpel: Das `i` ist ein besch… Name für jeweils das aktuelle Element der Liste die ``soup('td', {'class': 'Bleft'})`` zurück gibt. Das ganze Konstrukt ist eine „list comprehension”:

Code: Alles auswählen

result = [f(x) for x in iterable if test(x)]

# <=>

result = list()
for x in iterable:
    if test(x):
        result.append(f(x))
Wobei der Test optional ist.

Bei solchen Sachen hilft es übrigens beim Entwickeln und Verstehen auch ungemein das in einer interaktiven Shell auszuprobieren. Dann sieht man was welcher Aufruf zurück gibt.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Das ist eine List-Comprehension. An das ``i`` wird in jedem Durchlauf der Schleife das aktuell betrachtete Objekt gebunden. Das wird in diesem Falle eine Art von Knoten-Objekt sein, wenn ich den Ausdruck hinten richtig interpretiere (hab noch nie mit BS gearbeitet). "Vorne" kannst Du dann einen beliebigen Ausdruck hinschreiben, der etwas zurück liefert, u.a. eben auch ein Methoden-Aufruf auf dem Objekt. Als Ergebnis erhältst Du eine Liste mit allen Ergebnissen der Operation.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Rumpel
User
Beiträge: 9
Registriert: Dienstag 5. August 2014, 08:32

Hi BlackJack, hi Hyperion

danke für die Erklärung, habe es nun verstanden.

Gruß Jan
BlackJack

BeautifulSoup4 kann übrigens mittlerweile auch CSS-Selektoren, und hat „pythonischere” Aliasnamen für die im Java-Stil benannten Methoden (`findAll()` → `find_all()`).

Code: Alles auswählen

import requests
from bs4 import BeautifulSoup


def main():
    url = 'http://www.berliner-ensemble.de/spielplan'

    soup = BeautifulSoup(requests.get(url).text)
    iframe_urls = [iframe['src'] for iframe in soup.select('td.Bleft iframe')]

    for iframe_url in iframe_urls:
        soup = BeautifulSoup(requests.get(iframe_url).text)
        columns = [cell.get_text(' ', True) for cell in soup('td')]
        print columns


if __name__ == '__main__':
    main()
Edit: Das extrahieren des Textes etwas verbessert.
Antworten