preface
Web sites are increasingly using Ajax technology, which makes it difficult to determine when an element is fully loaded. If the actual page waits too long for a DOM element to appear, but your code uses the WebElement directly, NullPointer will be raised. There are also cases where you open a website, for example, if your Internet connection is slow, your code will be executed before the page has even loaded. At this point your program will report an error. To solve this problem. So Selenium provides two types of waiting: implicit and explicit.
In actual combat
An implicit wait
We used python’s built-in time module to enforce a wait of two seconds to solve these problems. Let’s do this in code
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
time.sleep(2)
driver.find_element_by_id('kw').send_keys('python')
Copy the code
The execution result
This type of wait is mandatory. The wait time is 2 seconds regardless of success. We’re going to try to write as little as possible in our code, and that’s going to make our code look really bad so let’s look at implicit waiting.
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
driver.implicitly_wait(2)
driver.find_element_by_id('kw').send_keys('python')
Copy the code
The execution result
The effect is similar. But instead of waiting two seconds, we just opened the page. So implicit wait if I find the tag I just open it, if I don’t find it I wait 2 seconds and then I look for it, if I don’t find it I throw an exception. So implicit waiting is friendlier
According to wait
A class is required to display the wait
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
Copy the code
The sample code
driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
Copy the code
What does this code mean? Is to pass a drive and time. Until is our condition. EC is the alias of the desired condition we set above. One of the ways that proesence_of_element_located conditions come up in this case is by id. So what is id? That’s the myDynamicElement in the back
Below we use 12306 this website to demonstrate if we want to buy a ticket, must be to fill in the departure destination and departure date
Note that the 12306 input tag is a little different from the normal input tag. It’s not going to read changsha and Beijing in this case but it’s going to read a value in it which is CSQ which is the code for Changsha. So when you query it is based on this code to operate, it is very troublesome
So we can do this. I’m going to wait before I click query. The origin and destination data appear. If it does, I click on the query action
Let’s go ahead and get the query button
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
# display wait
driver.get('https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc')
# Locate the query button
btn = driver.find_element_by_id('query_ticket')
btn.click()
Copy the code
At this time tell us the origin and destination must be filled in before you can click query. So here we can use display wait
So what is our condition such as my departure to enter changsha this 2 words
# Conditions of departure
WebDriverWait(driver,100).until(
EC.text_to_be_present_in_element_value((By.ID,'fromStationText'),'the changsha')
)
Copy the code
So here’s the destination condition and the principle is the same
# Destination conditions
WebDriverWait(driver,100).until(
EC.text_to_be_present_in_element_value((By.ID,'toStationText'),'Beijing')
)
Copy the code
All the conditions are true, we click query run
So that’s what we want. The effect is out, but don’t hurry up and try it.