from selenium import webdriver# 创建webdriver对象并指明使用chrome浏览器驱动# r表示原生字符串,不存在转义wd = webdriver.Chrome(r'd:\chromedriver.exe')# 调用webdriver对象的get方法, 可以让浏览器打开指定的网址# wd.get('http://www.baidu.com')wd.get('http://www.baidu.com')element = wd.find_element_by_id('kw')element.send_keys('别再问我什么是迪斯科')# id为 1 的元素,就是第一个搜索结果element = wd.find_element_by_id('1')# 打印出第一个搜索结果的文本字符串print(element.text)
报错了:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {“method”:”css selector”,”selector”:”[id=”1”]”} (Session info: chrome=84.0.4147.89)
原因
因为我们的代码执行的速度比 百度服务器响应的速度 快。
百度还没有来得及 返回搜索结果,我们就执行了如下代码
element = wd.find_element_by_id('1')
在那短暂的瞬间, 网页上是没有用 id为1的元素的 (因为还没有搜索结果呢)。自然就会报告错误 id为1 的元素不存在了。
解决
使用sleep让当前进程休眠几秒钟,等待服务器返回结果后,再去获取元素。
import timefrom selenium import webdriver# 创建webdriver对象并指明使用chrome浏览器驱动# r表示原生字符串,不存在转义wd = webdriver.Chrome(r'd:\chromedriver.exe')# 调用webdriver对象的get方法, 可以让浏览器打开指定的网址# wd.get('http://www.baidu.com')wd.get('http://www.baidu.com')element = wd.find_element_by_id('kw')element.send_keys('别再问我什么是迪斯科')time.sleep(1)# id为 1 的元素,就是第一个搜索结果element = wd.find_element_by_id('1')# 打印出第一个搜索结果的文本字符串print(element.text)
进一步的问题
如何设置等待时间?有没有更合理的解决方案。
Selenium提供了一个更合理的解决方案,是这样的:
当发现元素没有找到的时候, 并不 立即返回 找不到元素的错误。
而是周期性(每隔半秒钟)重新寻找该元素,直到该元素找到,
或者超出指定最大等待时长,这时才 抛出异常(如果是 find_elements 之类的方法, 则是返回空列表)。
Selenium 的 Webdriver 对象 有个方法叫 implicitly_wait
该方法接受一个参数, 用来指定 最大等待时长。
如果我们 加入如下代码
wd.implicitly_wait(10)
那么后续所有的 find_element 或者 find_elements 之类的方法调用 都会采用上面的策略:
如果找不到元素, 每隔 半秒钟 再去界面上查看一次, 直到找到该元素, 或者 过了10秒 最大时长。
这样,我们的百度搜索的例子的最终代码如下:
import timefrom selenium import webdriver# 创建webdriver对象并指明使用chrome浏览器驱动# r表示原生字符串,不存在转义wd = webdriver.Chrome(r'd:\chromedriver.exe')# 设置最大等待时间wd.implicitly_wait(10)# 调用webdriver对象的get方法, 可以让浏览器打开指定的网址# wd.get('http://www.baidu.com')wd.get('http://www.baidu.com')element = wd.find_element_by_id('kw')element.send_keys('别再问我什么是迪斯科')time.sleep(1)# id为 1 的元素,就是第一个搜索结果element = wd.find_element_by_id('1')# 打印出第一个搜索结果的文本字符串print(element.text)
