你好我是安然无虞。文章目录选择元素的基本方法根据 id属性 选择元素根据 class属性、tag名 选择元素根据 class属性 选择元素根据 tag名 选择元素find_element 和 find_elements方法的区别通过 WebElement 对象选择元素等待界面元素出现Selenium练习: 访问天气查询网站选择元素的基本方法根据 id属性 选择元素上一篇文章有讲解该方法, 请阅读: Python自动化测试·Selenium简单介绍根据 class属性、tag名 选择元素根据 class属性 选择元素Web自动化的难点和重点之一, 就是如何 选择 我们想要操作的 Web页面元素.除了根据元素的id值, 我们还可以根据元素的 class属性值 选择元素.就像一个 学生张三 可以定义类型为 中国人或学生一样, 中国人和学生都是张三的类型.元素也有类型, class属性就用来标志着元素类型.我们点击这个教学网址这个网址对应的HTML内容 有如下的部分:bodydivclassplantspan土豆/span/divdivclassplantspan洋葱/span/divdivclassplantspan白菜/span/divdivclassanimalspan狮子/span/divdivclassanimalspan老虎/span/divdivclassanimalspan山羊/span/div/body所有的植物元素都有个class属性 值为 plant.所有的动物元素都有个class属性 值为 animal.如果我们要选择所有的动物, 就可以像下面这样写:wd.find_elements(By.CLASS_NAME,animal)注意这里是elements而不是element.注意:find_elements() 返回的是找到的符合条件的 所有元素 (这里有3个符合条件的元素), 放在一个列表中返回.而如果我们使用 find_element() 方法, 就只会返回 第一个元素.我们运行如下代码看看:fromseleniumimportwebdriverfromselenium.webdriver.common.byimportBy# 创建 WebDriver 实例对象指明使用chrome浏览器驱动wdwebdriver.Chrome()# WebDriver 实例对象的get方法 可以让浏览器打开指定网址wd.get(https://www.byhy.net/cdn2/files/selenium/sample1.html)# 根据 class name 选择元素返回的是 一个列表# 里面 都是class 属性值为 animal的元素对应的 WebElement对象elementswd.find_elements(By.CLASS_NAME,animal)# 取出列表中的每个 WebElement对象打印出其text属性的值# text属性就是该 WebElement对象对应的元素在网页中的文本内容forelementinelements:print(element.text)执行结果如下:狮子 老虎 山羊首先我们要注意:通过 WebElement 对象的text属性可以获取该元素 在网页中的文本内容.所以下面的代码, 可以打印出 element 对应网页元素的文本.print(element.text)如果我们把上面的 find_elements() 方法换成 find_element() 方法:elementwd.find_element(By.CLASS_NAME,animal)print(element.text)那么返回的就是第一个 class 属性值为 animal的元素, 也就是这个元素:divclassanimalspan狮子/span/div就像一个学生张三可以定义有多个类型: 中国人和学生, 中国人 和 学生 都是张三的类型.元素也可以有多个 class 类型, 多个class类型的值之间用 空格隔开, 比如:spanclasschinese student张三/span注意, 这里的span元素有两个class属性, 分别是chinese和student, 而不是一个名为 Chinese student 的属性.我们要用代码选择这个元素, 可以指定任意一个 class属性值, 都可以选择到这个元素, 如下:elementwd.find_elements(By.CLASS_NAME,chinese)或者elementwd.find_elements(By.CLASS_NAME,student)但是注意, 不能写成这样:elementwd.find_elements(By.CLASS_NAME,chinese student)根据 tag名 选择元素类似的, 我们可以通过指定参数为 By.TAG_NAME, 选择所有的 tag名 为div 的元素, 如下所示:fromseleniumimportwebdriverfromselenium.webdriver.common.byimportBy wdwebdriver.Chrome()wd.get(https://www.byhy.net/cdn2/files/selenium/sample1.html)# 根据 tag name 选择元素返回的是 一个列表# 里面 都是 tag 名为 div 的元素对应的 WebElement对象elementswd.find_elements(By.TAG_NAME,div)# 取出列表中的每个 WebElement对象打印出其text属性的值# text属性就是该 WebElement对象对应的 元素在**网页中的文本内容**forelementinelements:print(element.text)find_element 和 find_elements方法的区别使用 find_elements 方法选择的是符合条件的 所有元素, 并将结果存放到一个列表中返回, 如果没有符合条件的元素, 就返回空列表.使用 find_element 方法选择的是符合条件的 第一个元素, 如果没有符合条件的元素, 就会抛出 NoSuchElementException 异常.通过 WebElement 对象选择元素不仅 WebDriver 对象有 选择元素的方法, WebElement 对象也有 选择元素的方法.WebElement对象 也可以调用 find_elements(), find_element()之类的方法.WebDriver对象 选择元素的范围是 整个 web页面, 而 WebElement对象 选择元素的范围是 该元素的内部.fromseleniumimportwebdriverfromselenium.webdriver.chrome.serviceimportServicefromselenium.webdriver.common.byimportBy wdwebdriver.Chrome(serviceService(r/Users/sunlei/Desktop/chromedriver))wd.get(https://www.byhy.net/cdn2/files/selenium/sample1.html)elementwd.find_element(By.ID,container)# 限制选择元素的范围是 id 为 container 元素的内部spanselement.find_elements(By.TAG_NAME,span)forspaninspans:print(span.text)input()执行结果如下:内层11 内层12 内层21等待界面元素出现在我们进行网页操作的时候, 有的元素内容不是可以立即出现的, 可能会等待一段时间.比如我们的股票搜索示例页面, 搜索一个股票名称, 我们点击搜索后, 浏览器需要把这个搜索请求发送给服务器进行处理后, 再把搜索结果返回给我们.所以, 从点击搜索到得到结果, 需要一定的时间.只是通常服务器处理速度比较快, 我们感觉好像立即得到了搜索结果.搜索的每个结果对应的界面元素, 其 ID 分别是数字 1, 2, 3, 4 …我们可以先用如下代码将第一个搜索结果里面的文本内容打印出来.fromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.chrome.serviceimportService wdwebdriver.Chrome(serviceService(r/Users/sunlei/Desktop/chromedriver))wd.get(https://www.byhy.net/cdn2/files/selenium/stock1.html)elementwd.find_element(By.ID,kw)element.send_keys(通讯\n)# 返回页面 ID为1 的元素elementwd.find_element(By.ID,1)print(element.text)运行之后, 我们发现抛出异常了.selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {method:css selector,selector:[id1]}NoSuchElementException 的意思就是在当前的网页中没有找到该元素, 就是找不到 id 为 1 的元素.这是为什么呢, 按道理来说是存在这个 id 为 1 的元素的.其实是因为我们的代码执行的速度比网站响应的速度快.网站还没有来得及返回搜索结果, 我们就执行了后续代码:elementwd.find_element(By.ID,1)在那短暂的瞬间, 网页上是没有用 id 为 1 的元素的 (因为还没有搜索到结果). 这样的话程序有上面的报错是可以理解的.那么怎么解决这个问题呢?聪明的你可能会想到, 点击搜索后, 用 sleep 来等待几秒钟, 等百度服务器返回结果后, 再去选择 ID 为 1 的元素.就像下面这样:fromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.chrome.serviceimportService wdwebdriver.Chrome(serviceService(r/Users/sunlei/Desktop/chromedriver))wd.get(https://www.byhy.net/cdn2/files/selenium/stock1.html)elementwd.find_element(By.ID,kw)element.send_keys(通讯\n)fromtimeimportsleep sleep(1)# 返回页面 ID为1 的元素elementwd.find_element(By.ID,1)print(element.text)运行之后是可以的, 没有之前的报错了.但是按照上面的方式有个很大的问题, 就是: 设置等待多长时间合适呢?这次百度网站反应可能比较快, 我们等待了1秒钟就可以了.但是谁知道下次它的反应时间是不是还这么快呢? 毕竟曾经百度也出现过服务器瘫痪的事情.可能有的老铁会说, 那我就等待久一点的时间, 等待20秒, 总归可以了吧.这样也有一个很大的问题, 假如一个自动化程序里面需要10次等待, 就要花费200秒等待时间. 而大部分时间, 服务器的反应是很快的, 根本不需要等待20秒, 这样就造成了大量的时间浪费.所以, Selenium 提供了一个更合理的解决方案, 是这样的:当发现元素没有找到的时候,并不立即返回找不到元素的错误.而是周期性 (每隔半秒钟) 重新寻找该元素, 直到找到该元素, 或者超出指定最大等待时长, 这时才抛出异常 (如果是 find_elements() 之类的方法, 则返回空列表.)Selenium 的 WebDriver 对象 有个方法叫implicitly_wait, 可以称之为隐式等待, 或者全局等待.这个方法接受一个参数, 用来指定最大等待时长.如果我们加入如下代码:wd.implicitly_wait(10)那么后续所有的 find_element() 或者 find_elements() 之类的方法调用都会采用上面的策略:如果找不到元素, 每隔半秒钟再去界面上查看一次, 直到找到该元素, 或者过了10秒最大时长.这样我们最终的代码应该是这样的:fromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.chrome.serviceimportService wdwebdriver.Chrome(serviceService(r/Users/sunlei/Desktop/chromedriver))wd.implicitly_wait(10)wd.get(https://www.byhy.net/cdn2/files/selenium/stock1.html)elementwd.find_element(By.ID,kw)element.send_keys(通讯\n)# 返回页面 ID为1 的元素elementwd.find_element(By.ID,1)print(element.text)运行之后, 我们发现没有之前的错误了.那么是不是有了 implicitly_wait(), 可以彻底不用 sleep()了呢?不是的, 有的时候我们等待元素出现, 仍然需要sleep().Selenium练习: 访问天气查询网站题目: 访问天气查询网站网址如下https://www.byhy.net/cdn2/files/selenium/jsweather.html往下翻一页会看到有 标题为城市预报列表 (2021-08-09 18:00发布)下面列出了江苏所有城市在某天的天气请写代码获取江苏所有城市的天气并找出其中每天最低气温最低的城市显示出来比如 温度最低为12℃, 城市有连云港 盐城代码如下:# 请写代码获取江苏所有城市的天气并找出其中每天最低气温最低的城市显示出来比如 温度最低为12℃, 城市有连云港 盐城fromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.chrome.serviceimportService wdwebdriver.Chrome(serviceService(r/Users/sunlei/Desktop/chromedriver))wd.get(rhttps://www.byhy.net/cdn2/files/selenium/jsweather.html)elementwd.find_element(By.ID,forecastID)print(element.text) citysWeather是每个城市的温度信息 list 每个元素像这样 南京 12℃/27 citiesWeatherelement.text.split(℃\n)# 计算温度最低的城市lowest70lowestCity[]# 温度最低城市列表foroneincitiesWeather:oneone.replace(℃,)print(one)curcityone.split(\n)[0]lowweatherone.split(/)[0].split(\n)[1]lowweatherint(lowweather)iflowweatherlowest:lowestlowweather lowestCity[curcity]eliflowweatherlowest:lowestCity.append(curcity)print(温度最低为%s℃, 城市有%s%(lowest, .join(lowestCity)))input()遇见安然遇见你不负代码不负卿。谢谢老铁的时间咱们下篇再见