Nun, ich mochte es nicht, wenn die Maus im Geschäftssystem flatterte (Anwesenheitsverwaltung).
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.
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
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.
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.
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:
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