1. from selenium import webdriver
  2. # 创建webdriver对象并指明使用chrome浏览器驱动
  3. # r表示原生字符串,不存在转义
  4. wd = webdriver.Chrome(r'd:\chromedriver.exe')
  5. # 调用webdriver对象的get方法, 可以让浏览器打开指定的网址
  6. # wd.get('http://www.baidu.com')
  7. wd.get('http://www.baidu.com')
  8. element = wd.find_element_by_id('kw')
  9. element.send_keys('别再问我什么是迪斯科')
  10. # id为 1 的元素,就是第一个搜索结果
  11. element = wd.find_element_by_id('1')
  12. # 打印出第一个搜索结果的文本字符串
  13. 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)

原因

因为我们的代码执行的速度比 百度服务器响应的速度 快。
百度还没有来得及 返回搜索结果,我们就执行了如下代码

  1. element = wd.find_element_by_id('1')

在那短暂的瞬间, 网页上是没有用 id为1的元素的 (因为还没有搜索结果呢)。自然就会报告错误 id为1 的元素不存在了。

解决

使用sleep让当前进程休眠几秒钟,等待服务器返回结果后,再去获取元素。

  1. import time
  2. from selenium import webdriver
  3. # 创建webdriver对象并指明使用chrome浏览器驱动
  4. # r表示原生字符串,不存在转义
  5. wd = webdriver.Chrome(r'd:\chromedriver.exe')
  6. # 调用webdriver对象的get方法, 可以让浏览器打开指定的网址
  7. # wd.get('http://www.baidu.com')
  8. wd.get('http://www.baidu.com')
  9. element = wd.find_element_by_id('kw')
  10. element.send_keys('别再问我什么是迪斯科')
  11. time.sleep(1)
  12. # id为 1 的元素,就是第一个搜索结果
  13. element = wd.find_element_by_id('1')
  14. # 打印出第一个搜索结果的文本字符串
  15. print(element.text)

进一步的问题

如何设置等待时间?有没有更合理的解决方案。
Selenium提供了一个更合理的解决方案,是这样的:
当发现元素没有找到的时候, 并不 立即返回 找不到元素的错误。
而是周期性(每隔半秒钟)重新寻找该元素,直到该元素找到,
或者超出指定最大等待时长,这时才 抛出异常(如果是 find_elements 之类的方法, 则是返回空列表)。
Selenium 的 Webdriver 对象 有个方法叫 implicitly_wait
该方法接受一个参数, 用来指定 最大等待时长。
如果我们 加入如下代码

  1. wd.implicitly_wait(10)

那么后续所有的 find_element 或者 find_elements 之类的方法调用 都会采用上面的策略:
如果找不到元素, 每隔 半秒钟 再去界面上查看一次, 直到找到该元素, 或者 过了10秒 最大时长。

这样,我们的百度搜索的例子的最终代码如下:

  1. import time
  2. from selenium import webdriver
  3. # 创建webdriver对象并指明使用chrome浏览器驱动
  4. # r表示原生字符串,不存在转义
  5. wd = webdriver.Chrome(r'd:\chromedriver.exe')
  6. # 设置最大等待时间
  7. wd.implicitly_wait(10)
  8. # 调用webdriver对象的get方法, 可以让浏览器打开指定的网址
  9. # wd.get('http://www.baidu.com')
  10. wd.get('http://www.baidu.com')
  11. element = wd.find_element_by_id('kw')
  12. element.send_keys('别再问我什么是迪斯科')
  13. time.sleep(1)
  14. # id为 1 的元素,就是第一个搜索结果
  15. element = wd.find_element_by_id('1')
  16. # 打印出第一个搜索结果的文本字符串
  17. print(element.text)