Möchten Sie mit Python Selenium auf allgemeine Zwecke warten?

Einführung

Nun, ich mochte es nicht, wenn die Maus im Geschäftssystem flatterte (Anwesenheitsverwaltung).

Gemeinsame Dinge beim Krabbeln

Grundsätzlich handelt es sich um ein System, bei dem Menschen mit einer Maus flattern, sodass nicht davon ausgegangen wird, dass es von einer Maschine bedient wird. Es gibt die Voraussetzung, dass Sie niemals eine Taste drücken, die Sie noch nicht gesehen haben. Wenn Sie also darüber nachdenken, sie je nach Person zu verschieben, tun Sie etwas, wenn Sie sie richtig drücken oder wenn Sie sie eingeben können Es ist notwendig, das Timing so zu steuern.

Selen hat natürlich einen solchen Mechanismus.

Dokument: wartet, Wartezeiten, Wartezeit (Übersetzung oben)

Das zweite und dritte Dokument zeigen zwei Möglichkeiten. Nur auf eine bestimmte Zeit in den dunklen Wolken zu warten, ist eine implizite Wartezeit, und Sie müssen es nicht Selenium-san überlassen, um Zeit zu haben. Nun, es ist leicht zu sagen, dass es einfach ist, weil Sie keine Kosten eingeben oder vergessen müssen, sie einzugeben. Wenn sich die Antwortgeschwindigkeit jedoch in Abhängigkeit von den Netzwerkbedingungen und den PC-Lastbedingungen unterscheidet, erhalten Sie möglicherweise nicht die erwarteten Ergebnisse, sodass dies im Wesentlichen explizit ist. Warten ist wünschenswert. Aber [interne Abfrage für einen bestimmten Zeitraum (Standard 0,5 s)](https://seleniumhq.github.io/selenium/docs/api/py/_modules/selenium/webdriver/support/wait.html# WebDriverWait), sodass die Verarbeitungslast etwas höher ist.

Wie man wartet

In dem im obigen Dokument beschriebenen Beispiel wird es also wie folgt gezeigt.

#Der erste
element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id(“someId”))

#2. und 3 ..
try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "myDynamicElement"))
    )
finally:
    #Ausnahmebehandlung

Passen Sie die Wartebedingungen an

Darüber hinaus beschreibt dieses Dokument das Anpassen. .. In ExceptedConditions definierte Hilfsklasse, wie z. Ich benutze. Diese Methode kann jedoch verstanden werden, wenn sie etwas komplizierter ist, aber wenn sie so einfach ist wie die vorgestellte, kann sie einfacher durchgeführt werden.

Sie können eine benutzerdefinierte Wartebedingung mit einer Klasse erstellen, die über eine call- Methode verfügt, die False zurückgibt, wenn die Bedingungen nicht übereinstimmen.

Sie müssen nur die Bedingungen wie beibehalten, damit Sie einen Lambda-Ausdruck oder etwas anderes verwenden können. (Es wird im allerersten Dokument erwähnt.)

def proc(driver, type, name, cname):
  #Erstellen Sie den Prozess, den Sie anpassen möchten, geben Sie False zurück, wenn die Bedingungen nicht übereinstimmen, und geben Sie das Element zurück, wenn dies erfolgreich ist
  element = driver.find_element(type, name)
  if cname in element.get_attribute("class"):
    return element
  else:
    return False

wait = WebDriverWait(driver, 10)
try:
  element = wait.until(lambda drv: proc(drv, By.ID, 'myNewInput', 'myCSSClass'))
except TimeoutException:
  print("timeout..")
  sys.exit()

Ein Beispiel für einen Lamda-Ausdruck ist [dieses Dokument](https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.wait.html?highlight=webdriverwait#selenium.webdriver.support .wait.WebDriverWait ) Wird auch beschrieben. Dieses Dokument enthält einen Link zur Quelle, daher halte ich es für sehr nützlich. Wenn Sie sich hier beziehen, besteht der Punkt darin, dass Sie eine Bedingung hinzufügen können, z. B. nicht nur ein Element abrufen, wenn es gefunden wird, sondern auch ein Element mit einem bestimmten Attribut.

Das Hauptthema?

Nun, im ersten Beispiel haben wir bestätigt, dass die ID im DOM vorhanden ist. Beispielsweise kann das zu bestätigende Element eine Klasse oder ein Name sein und das Element, das je nach Seite und Konfiguration auf Änderungen wartet. Zu diesem Zeitpunkt ist dies By.CLASS_NAME, und ich wollte vermeiden, Kennungen wie By.NAME (in Bezug auf die Codierung) zu kennen. Natürlich müssen Sie beim Crawlen darüber nachdenken, wie einfach es ist, weil dieses Element von der ID abgerufen wird, und wie Sie es eindeutig identifizieren können, weil es eine Klasse ist. Daher habe ich vorerst einen kleinen Wartevorgang basierend auf dem obigen Beispiel durchgeführt. Ich habe es nicht richtig bestätigt.

def wait(drv, sec, selector):
    def chk(selector):
        elem = drv.find_element(By.ID, selector)
        if elem:
            return elem
        elem = drv.find_element(By.CLASS_NAME, selector)
        #print("css:",type(elem), elem)
        if elem:
            return elem
        elem = drv.find_element(By.XPATH, selector)
        if elem:
            return elem
        elem = drv.find_elements(By.ID, selector)
        if elem:
            return elem
        elem = drv.find_elements(By.CLASS_NAME, selector)
        if elem:
            return elem
        return False

    try:
        elem = WebDriverWait(drv, sec).until(
            lambda _: chk(selector)
        )
        return elem
    except TimeoutException:
        print(f"wait timeout.. {selector} not found")
        return None

elem = wait(driver, 10, "elem_name")
if not elem:
    print("wow, unknown error.")

Es ist so ähnlich, aber ich kann nicht verzeihen, dass das chk ein bisschen redundant ist und find_element oft gemacht wird. Darüber hinaus können die Elemente, die erhalten werden können, Listen sein. .. In diesem Sinne scheint es besser, die Denkweise ein wenig zu ändern.

Außerdem bietet stackoverflow eine Beispiellösung zum Erstellen Ihrer eigenen Klasse. Übergeben Sie den Prüfungsteil in einer Liste, und wenn einer trifft, ist es in Ordnung. Es ist ziemlich schlau, also lasst es uns so organisieren, dass es mit dieser Idee richtig funktioniert.

Finale Form

Warten Sie die Implementierung so

class AnyEc:
        """ Use with WebDriverWait to combine expected_conditions
                in an OR.
        """""
        def __init__(self, *args):
                if type(args) is tuple:
                        lval = list(args)
                else:
                        lval = args

                self.ecs = []
                for v in lval:
                        if type(v) is list:
                                self.ecs += v
                        else:
                                self.ecs.append(v)

                print("ecs type: ", type(self.ecs))
        def __call__(self, driver):
                #print("ecs: ", self.ecs)
                for fn, param in self.ecs:
                        r = fn(param)
                        print("param: ", param, r)
                        if r :
                                return r
                return False

def wait_any(drv, sec, *args):
        try:
                elem = WebDriverWait(drv, sec).until(
                        AnyEc(*args)
                )
                return elem
        except TimeoutException:
                print(f"wait timeout.. {args} not found")
                return False

Wie benutzt man

def make_css_selector(key):
        value = []
        value += ['[id="%s"]' % key]
        value += ['#%s' % key]
        value += [key]
        value += ['[name="%s"]' % key]
        value += [".%s" % key]
        return value

#Verwendungsbeispiel

#URL zum Zugriff
url='https://ja.stackoverflow.com/'
#Das Tag, das Sie finden möchten
str='question-mini-list h3'
#Überlass es mir
val = make_css_selector(str)
fn = [(driver.find_elements_by_css_selector, x) for x in val]

driver = webdriver.Chrome()
driver.get(url)

try :
  #Warten Sie, bis Sie das gesuchte Tag gefunden haben. Nach 10 Sekunden tritt eine Zeitüberschreitung auf
  elem = wait_any(driver, 10, fn)
  for e in elem:
    print(e.text)

finally:
  driver.close()
  driver.quit()

Es sieht doch nicht so schlau aus: heat_smile:

Beiseite

Ursprünglich wollte ich XPath mit oder so kombinieren, damit es auf einmal gemacht werden kann, aber ich gab auf, weil es schwierig war, zu XPath zu konvertieren: stick_out_tongue_winking_eye:

Schauen wir uns übrigens die Quelle von find_element an. https://seleniumhq.github.io/selenium/docs/api/py/_modules/selenium/webdriver/remote/webdriver.html#WebDriver.find_element

        if self.w3c:
            if by == By.ID:
                by = By.CSS_SELECTOR
                value = '[id="%s"]' % value
            elif by == By.TAG_NAME:
                by = By.CSS_SELECTOR
            elif by == By.CLASS_NAME:
                by = By.CSS_SELECTOR
                value = ".%s" % value
            elif by == By.NAME:
                by = By.CSS_SELECTOR
                value = '[name="%s"]' % value
        return self.execute(Command.FIND_ELEMENT, {
            'using': by,
            'value': value})['value']

Tatsächlich hat es sich fast in CSS_SELECTOR geändert. Wenn ich es also nicht in XPath angeben musste, dachte ich, dass ich einen Fund verwenden könnte, aber es funktionierte nicht, also gab ich hier auf.

Recommended Posts

Möchten Sie mit Python Selenium auf allgemeine Zwecke warten?
Ich möchte Dunnetts Test in Python machen
Warten Sie, bis sich in Selen ein weiteres Fenster öffnet
Wenn Sie in der for-Anweisung plt.save möchten
Ich möchte am Ende etwas mit Python machen
Was tun, wenn in Hydrogen "Kein Kernel für Sprachpython gefunden" angezeigt wird?
Was tun, wenn `Argumente [0] .scrollIntoView ();` in Python-Selen fehlschlägt?
Ich möchte so etwas wie Uniq in Python sortieren
[Python] Wie man PCA mit Python macht
Ich suche einen einheitlichen Weg, um auf Statusänderungen von Selenium für Python-Elemente zu warten
[Unterprozess] Wenn Sie ein anderes Python-Programm in Python-Code ausführen möchten
Was tun, wenn in Python minus Null angezeigt wird?
[Python] Wenn Sie alle Variablen in einer anderen Datei verwenden möchten
Wenn Sie einer Variablen in Python einen CSV-Export zuweisen möchten
So machen Sie R chartr () in Python
Lassen Sie uns zusammenfassen, was Sie tun möchten.
Was tun, wenn Sie die Rastersuche von sklearn in Python nicht verwenden können?
Was tun, wenn in pydoc keine Python-Dokumentation für ... gefunden wird?
Wenn Sie Wörter in Python zählen möchten, können Sie bequem Counter verwenden.
Ich möchte Affenpatches nur teilweise sicher mit Python machen
Ich möchte mit Python ein Fenster erstellen
Minimale Implementierung von Union Find in Python
Ich möchte verschachtelte Dicts in Python zusammenführen
Melden Sie sich mit Selenium Python bei Yahoo Business an
Versuchen Sie, RPN mit Python zu berechnen (für Anfänger)
Was tun, um eine Google-Tabelle in Python zu erhalten?
Ich möchte den Fortschritt in Python anzeigen!
Soll ich diese Kopie reparieren?
Verwenden Sie PIL in Python, um nur die gewünschten Daten aus Exif zu extrahieren
Was tun, wenn "Python nicht konfiguriert" angezeigt wird? Verwenden von PyDev in Eclipse
Ich möchte in Python schreiben! (1) Überprüfung des Codeformats
Ein Tool zum Erstellen von Maskenbildern für ETC in Python
[Für Anfänger] Wie man den Befehl say mit Python benutzt!
Ich möchte eine Variable in einen Python-String einbetten
Ich möchte Timeout einfach in Python implementieren
So führen Sie eine Hash-Berechnung mit Salt in Python durch
Schlüsseleingabe, die nicht auf Schlüsseleingabe in Python wartet
So führen Sie Python im virtuellen Raum aus (für MacOS)
Ich möchte in Python schreiben! (2) Schreiben wir einen Test
Auch mit JavaScript möchte ich Python `range ()` sehen!
Ich möchte eine Datei mit Python zufällig testen
Links, um mit Sublime Text zu tun, was Sie wollen
Was tun, wenn beim Importieren von matplotlib in Python (Mac) eine Fehlermeldung angezeigt wird?
Ich war süchtig danach, 2020 mit Selen (+ Python) zu kratzen
Ich möchte nur das 95% -Konfidenzintervall des Unterschieds im Bevölkerungsverhältnis in Python ermitteln
% Und str.format () in Python. Welches benutzt du?
Ich möchte mit einem Roboter in Python arbeiten.
So laden Sie Dateien von Selenium of Python in Chrome herunter
Ich möchte in Python schreiben! (3) Verwenden Sie Mock
Für diejenigen, die Python mit vim schreiben möchten
Um das Äquivalent von Rubys ObjectSpace._id2ref in Python zu tun
Ich möchte R-Datensatz mit Python verwenden
Ich möchte Strings in Kotlin wie Python manipulieren!
Was tun, wenn Sie Python auf IntelliJ ausführen und mit einem Fehler beenden?
Notieren Sie sich, was Sie in Zukunft mit Razpai machen möchten
Was tun, wenn Swagger-Codegen mit Python und Importfehler ausgeführt wird? Es wird kein Modul mit dem Namen angezeigt
[Python3] Code, der verwendet werden kann, wenn Sie die Größe von Bildern Ordner für Ordner ändern möchten
[Python] Wenn Sie Ihr eigenes Paket im oberen Verzeichnis importieren und verwenden möchten