Wie Iframe identifizieren?

2 Antworten

Vom Fragesteller als hilfreich ausgezeichnet
Jetzt frage ich mich zunächst einmal, weshalb das jedes mal aufgeht, wenn ich den Code ausführe, aber nur ein einziges mal erschien, als ich das erste mal mit dem Gerät auf web.de war?!

Die Browserinstanz, die du da öffnest, nutzt nicht die Cookies, die du mit dem Browser, mit dem du üblicherweise durch das Web surfst, gespeichert hast. Sie speichert sich auch keine Cookies. Es ist im Grunde so, als würdest du jedesmal ein absolut frisches, konfigurationsfreies Browserfenster öffnen.

Wie komme ich denn jetzt zum eigentl. Login?

Ein direkter Weg, das Popup wegzubekommen, wäre der Klick auf den von dir genannten Button. Um diesen zu erhalten, musst du zwischen verschiedenen Framekontexten springen.

Der erste Schritt sollte aber erst einmal das Warten auf den Popup sein (bzw. auf das in ihm enthaltene iFrame). Selenium wartet zwar automatisch bis die Seite geladen wird. So ein Popup erscheint aber erst danach und hat seine separate Ladedauer.

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome()
driver.maximize_window()
driver.get('https://www.web.de/')

try:
  frame = WebDriverWait(driver, 5).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "iframe[name='landingpage']")))
  # do something with frame ...
except TimeoutException:
  print("Popup needs to much time for loading.")

Ich habe an dieser Stelle einen Timeout von fünf Sekunden angesetzt. Du kannst aber auch einen anderen Wert verwenden, wenn dir dieser Wert zu hoch ist oder du merken solltest, dass der Popup bei dir länger braucht.

Im Anschluss müsstest du in den ersten iFrame springen:

driver.switch_to.frame(frame);

Und von dort aus geht es gleich weiter in den nächsten (inneren):

innerFrame = driver.find_element_by_tag_name("iframe")
driver.switch_to.frame(innerFrame)

Bei der Selektion des inneren Frames braucht man meines Erachtens keinen komplexen Selektor. Gleich das erste Element ist das, welches gesucht wird.

Im inneren Frame kannst du nun den Button suchen. Nimm die ID für die Selektion. Sie ist eindeutig und weniger komplex. Außerdem ist die Wahrscheinlichkeit, dass sie sich ändert, viel geringer, als es bei der Beschriftung des Buttons der Fall ist. Gerade bei den Cookie-Popups gibt es öfter Änderungen und Wortklaubereien zwischen verschiedenen Rechtsabteilungen und auch abgesehen davon würde ich dir raten, dich bestenfalls nie an Content zu orientieren, sondern stets am HTML. Inhaltliche Änderungen werden eher durchgeführt, als technische.

driver.find_element_by_id("save-all-conditionally").click()

Mit:

driver.switch_to.default_content();

kommst du übrigens wieder in den Startkontext, wenn du mit Selektionen / Änderungen im iFrame fertig bist.

In deinem Fall wird dieser Aufruf aber nicht notwendig sein, denn die Zustimmung des Popups sorgt ebenso für ein Neuladen der Seite (web.de kann so nämlich auch gleich all die Cookies setzen, die vom Nutzer erlaubt wurden).

Für diese Zeit solltest du erneut etwas warten. Die maximale Wartezeit würde ich diesmal noch etwas nach oben schrauben. Diese beiden Zeilen:

username_input = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "freemailLoginUsername")))
username_input.send_keys("test")

sorgen dafür, dass das Eingabefeld für den Nutzernamen mit einem ersten Wert (test) beschrieben wird, sobald die Seite neu geladen wurde.

Regex20921518 
Fragesteller
 31.07.2021, 10:13

Danke für die ausführliche Antwort. Also wartet der erste Codeblock von dir sozusagen solange auf das Ereignis, dass ein bestimmtes Element auffindbar ist (until) und dann erst wird der nachfolgende Code ausgeführt? Warum funktioniert es denn dann nicht mit einem einfach time.wait(5)? Danke

0
regex9  31.07.2021, 10:37
@Regex20921518

Ja.

Du könntest auch mit time.sleep auf das Popup warten, aber die Methodik mit dem until-Aufruf löst das Problem viel sauberer für dich, denn es prüft in einem Zug, ob das Element innerhalb der Wartezeit erscheint.

Das heißt, wenn das Element bereits nach einer Sekunde da ist, geht es sofort mit der Ausführung weiter und die verbleibenden vier Sekunden werden verworfen. Mit sleep würdest du deine Anwendung in jedem Fall für eine bestimmte Zeit pausieren, auch wenn das Element schon längst sichtbar geworden ist.

0

ich würde behaupten das nur die engine genutzt wird und nicht unsicher das python deinen browser mit user profil nutzt , so wie du als user . ergo , das startet das mit einem selenimum profil .

Regex20921518 
Fragesteller
 28.07.2021, 12:54

Zu deutsch? Das sagt mir jetzt gar nichts.

0