【爬虫】5.6 Selenium等待HTML元素

目录

任务目标

创建Ajax网站

创建服务器程序

Selenium XX 等待

1. Selenium强制等待

2. Selenium隐性等待

3. Selenium循环等待

4. Selenium显示等待

等待方法


任务目标

  • 在浏览器加载网页的过程中,网页的有些元素时常会有延迟的现象,在HTML元素还没有准备好的情况下去操作这个HTML元素必然会出现错误,这个时候Selenium需要等待HTML元素。例如:上节实例中出现的select的下拉框元素,选项填充需要执行JavaScript脚本
  • 我们来学习如果使用Selenium等待延迟的HTML元素并最终爬取元素的数据。

创建Ajax网站

phone.html 如下:

注:phone.html 文件要位于 templates 这个目录下

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><form name="frm" action="/"><div><span id="msg"></span><label for="xmark"></label><select id="xmark"></select></div><input type="submit" value="提交" id="submit" disabled="true"></form>
</body>
<script>function loadMarks(){var http=new XMLHttpRequest(); http.open("get","/marks",true);http.send(null);http.onreadystatechange=function(){// onreadystatechange存储函数,每当 readyState 属性改变时,就会触发调用该函数。// readystate存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。// 0: 请求未初始化    1: 服务器连接已建立     2: 请求已接收    3: 请求处理中    4: 请求已完成,且响应已就绪// status,200(OK),404(未找到页面)if (http.readyState===4 && http.status===200){ //请求完成并且成功返回var xmark=document.getElementById("xmark"); var xcolor=document.getElementById("xcolor"); marks=eval("("+http.responseText+")");// JS中将JSON的字符串解析成JS对象格式for(var i=0;i<marks.length;i++) xmark.options.add(new Option(marks[i],marks[i])); document.getElementById("submit").disabled=false;document.getElementById("msg").innerHTML="品牌";}};}loadMarks();
</script>
</html>

创建服务器程序

服务器server.py程序如下:

import flask
import json
import timeapp = flask.Flask(__name__)@app.route("/")
def index():return flask.render_template("phone.html")@app.route("/marks")
def loadMarks():time.sleep(1)marks = ["华为", "苹果", "三星"]return json.dumps(marks)  # 将JSON的对象格式转化成str格式app.run()

模拟网站结果如下:


Selenium XX 等待

1. Selenium强制等待

必须等待的时间,缺点:不能准确把握需要等待的时间(有时操作还未完成,等待就结束了,导致报错;有时操作已经完成了,但等待时间还没有到,浪费时间),如果在用例中大量使用,会浪费不必要的等待时间,影响测试用例的执行效率。

from selenium import webdriver
from selenium.webdriver.common.by import By
import timedriver = webdriver.Chrome()
driver.get("http://127.0.0.1:5000")# 设置强制等待1.5秒,
time.sleep(1.5)marks = driver.find_elements(By.XPATH, "//select/option")
print("品牌数量:", len(marks))
for mark in marks:print(mark.text)
form = driver.find_element(By.XPATH, "//form")
print(form.get_attribute("innerHTML").strip())
time.sleep(5)
driver.close()

2. Selenium隐性等待

该方法是浏览器对象调用的方法,即设置浏览器打开网页均等待的时长, 同样如果设置的隐性等待时间不够长, 还是爬取不到需要的数据。

from selenium import webdriver
from selenium.webdriver.common.by import By
import timedriver = webdriver.Chrome()# 设置隐性加载时间1.5秒,即网页在加载时最长等待 seconds 秒
driver.implicitly_wait(1.5)driver.get("http://127.0.0.1:5000")
marks = driver.find_elements(By.XPATH, "//select/option")
print("品牌数量:", len(marks))
for mark in marks:print(mark.text)
form = driver.find_element(By.XPATH, "//form")
print(form.get_attribute("innerHTML").strip())
time.sleep(5)
driver.close()

3. Selenium循环等待

循环等待 实际上这个爬虫程序能否爬到数据的关键是<select>中是否已经出现了<option>元素,我们可以设置一个循环来判断是否有<option>元素

from selenium import webdriver
from selenium.webdriver.common.by import By
import timedriver = webdriver.Chrome()
try:driver.get("http://127.0.0.1:5000")waitTime = 0while waitTime < 10:marks = driver.find_elements(By.XPATH, "//select/option")if len(marks) > 0:breaktime.sleep(0.5)waitTime += 0.5if waitTime >= 10:raise Exception("Waiting time out")marks = driver.find_elements(By.XPATH, "//select/option")print("品牌数量:", len(marks))for mark in marks:print(mark.text)form = driver.find_element(By.XPATH, "//form")print(form.get_attribute("innerHTML").strip())
except Exception as err:print(err)
time.sleep(5)
driver.close()

循环等待 实际上这个爬虫程序能否爬到数据的关键是<select>中是否已经出现了<option>元素,我们可以设置一个循环来判断是否有<option>元素。 这个程序中使用 waitTime 变量来构造一个循环,它最长等待 10 秒,每间隔 0.5 秒就检查一次<select>中是否有<option>存在,如果找到了<option>元素就退出等待循环,不然就继续等待直到<option>出现为止,如果 10 秒内还没有出现据抛出异常。

4. Selenium显示等待

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import Bydriver = webdriver.Chrome()
try:driver.get("http://127.0.0.1:5000")# 显示等待locator = (By.XPATH, "//select/option")WebDriverWait(driver, 10, 0.5).until(EC.presence_of_element_located(locator))marks = driver.find_elements(By.XPATH, "//select/option")print("品牌数量:", len(marks))for mark in marks:print(mark.text)form = driver.find_element(By.XPATH, "//form")print(form.get_attribute("innerHTML").strip())
except Exception as err:print(err)

构造一个定位元素的 locator 的对象,例如通过 XPath 的方法定位<select>中的<option>元素:

locator=(By.XPATH,"//select/option")

使用 WebDriverWait 构造一个实例,调用 until 方法:

WebDriverWait(driver, 10,0.5).until(EC.presence_of_element_located(locator))

这条语句的含义是等待 locator 指定的元素出现,最长等待 10 秒,每间隔 0.5 秒就出现检查一次。如果在 10 秒内出现了该元素就是结束等待,否则就抛出一个异常,默认抛出异常为:NoSuchElementException。

这种等待的优点:等待判断准确,不会浪费多余的等待时间,在实际中使用可以提高执行效率。


等待方法

1. EC.presence_of_element_located(locator)

这种形式是 等待 locator指定的元素 出现 ,也就是HTML文档中建立起了这个元素。

2. EC.visibility_of_element_located(locator)

这种形式是 等待 locator指定的元素 可见 ,注意元素出现时未见得可见,

例如:

<select id="xmark" style="display:none">...</select>

那么元素<select>是出现的但是不可见。

3. EC.element_to_be_clickable(locator)

这种形式是 等待 locator指定的元素 可以被点击

例如,在爬虫程序中等待 <input type="submit"> 按钮可用被点击:

locator = (By.XPATH, "//input[@type='submit']")

WebDriverWait(driver, 10,0.5).until(EC.element_to_be_clickable(locator))

或者等待 <option> 是否可以被点击: locator = (By.XPATH, "//select/option") WebDriverWait(driver,10,0.5).until(EC.element_to_be_clickable(locator))

使用这两种方法都可以爬取到手机品牌数据。

但是注意使用: locator = (By.XPATH, "//select") WebDriverWait(driver,10,0.5).until(EC.element_to_be_clickable(locator))

是等待<select>是否可以点击,这个元素就是没有<option>时也是可以点击的,因此用这个等待是爬取不到手机的品牌数据的。

4. EC.element_located_to_be_selected(locator)

这种形式是 等待 locator指定的元素 可以被选择,可以被选择的元素一般是<select>中的选项<option>、输入的多选框 <input type="checkbox"> 以及输入的单选框 <input type="radio">等元素。

locator = (By.XPATH, "//select/option")

WebDriverWait(driver, 10,0.5).until(EC.element_located_to_be_selected(locator))

同样能爬取到手机的品牌数据。

但是使用下列是不行的:

locator = (By.XPATH, "//input[@type='submit']")

WebDriverWait(driver,   10,0.5).until(EC.element_located_to_be_selected(locator))

因为这样的 <input type='submit'> 是怎么样也不可以选择的。

5. EC.text_to_be_present_in_element(locator,text)

这种形式是等待 locator 指定的元素的文本中包含指定的text文本,例如爬虫程序中使用下列的等待:

locator = (By.ID, "msg")

WebDriverWait(driver, 10,0.5).until(EC.text_to_be_present_in_element(locator,"品"))

即等待<span id="msg">......</span>元素中的文本包含"品"字,由于在<option>出现后设置文本是"品牌",因此爬虫程序可以爬取到手机品牌数据。


下一篇文章:实验项目一:【文本反爬网站的分析和爬取】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/115229.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实战系列(一)| Dubbo和Spring Cloud的区别,包含代码详解

目录 1. 概述2. 核心功能3. 代码示例4. 适用场景 Dubbo 和 Spring Cloud 都是微服务架构中的重要框架&#xff0c;但它们的定位和关注点不同。Dubbo 是阿里巴巴开源的一个高性能、轻量级的 RPC 框架&#xff0c;主要用于构建微服务之间的服务治理。而 Spring Cloud 是基于 Spri…

华为OD机试 - 字符串分割(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路1、根据题意&#xff1a;2、例如&#xff1a;3、解题思路&#xff1a; 五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《…

金仓数据库KingbaseES Windows版本启动时报错的问题

服务启动提示&#xff1a; 原因是使用的授权版本不对&#xff0c;导致服务总是启动不了 先卸载&#xff0c;重启&#xff0c;重新安装&#xff0c;选择下面这个授权文件 再启动开发工具&#xff0c;成功

Mybatis 里面的缓存机制

Mybatis 里面设计的二级缓存是用来提升数据的检索效率&#xff0c;避免每次数据的访问都需要去查询数据库。 一级缓存&#xff0c;是 SqlSession 级别的缓存&#xff0c;也叫本地缓存&#xff0c;因为每个用户在执行查询的时 候都需要使用 SqlSession 来执行&#xff0c; 为了避…

Redis进阶 - JVM进程缓存

原文首更地址&#xff0c;阅读效果更佳&#xff01; Redis进阶 - JVM进程缓存 | CoderMast编程桅杆https://www.codermast.com/database/redis/redis-advance-jvm-process-cache.html 传统缓存的问题 传统的缓存策略一般是请求到达 Tomcat 后&#xff0c;先查询 Redis &…

Gitlab创建一个空项目

1. 创建项目 Project slug是访问地址的后缀&#xff0c;跟前边的ProjectUrl拼在一起&#xff0c;就是此项目的首页地址&#xff1b; Visibility Level选择默认私有即可&#xff0c;选择内部或者公开&#xff0c;就会暴露代码。 勾选Readme选项&#xff0c;这样项目内默认会带…

CANalyzer panel

(1205条消息) CAPL 脚本中对信号&#xff0c;系统变量&#xff0c;环境变量的 事件响应_capl programs脚本怎么写信号运算_蚂蚁小兵的博客-CSDN博客 注意环境变量是在工程关联的dbc中创建的&#xff1b;而系统变量是在CANoe工程工具栏的”Environment”下的”System Variables”…

不可变集合、Lambda表达式、Stream流

不可变集合、Lambda表达式、Stream流 创建不可变集合 不能被修改的集合 应用场景 如果某个数据不能被修改&#xff0c;把它防御性的拷贝到不可变集合中是个很好的实践。 当集合对象被不可信的库调用时&#xff0c;不可变形式是安全的。 创建不可变集合 在List、Set、Map接口中…

DP读书:鲲鹏处理器 架构与编程(十一)鲲鹏生态软件架构 AND 硬件特定软件

鲲鹏生态软硬件构成 鲲鹏软件构成硬件特定软件1. Boot Loader2. SBSA 与 SBBR3. UEFI4. ACPI 鲲鹏软件构成 鲲鹏处理器的软件生态是一个不断发展的软件生态&#xff0c;服务器本身也具有复杂度多样性&#xff0c;经过很长时间的发展服务器硬件有不同的操作系统方案&#xff0c…

C语言递归写n的k次方

int Func(int n,int k) {if (k 0){return 1;}else if (k > 1){return n * Func(n, k - 1);;}}int main() {int i 0;int j 0;printf("请输入数n和他的k次方\n");scanf("%d %d", &i,&j);int r Func(i,j);printf("%d的%d次方 %d\n"…

解决无法远程连接MySQL服务的问题

① 设置MySQL中root用户的权限&#xff1a; [rootnginx-dev etc]# mysql -uroot -pRoot123 mysql> use mysql; mysql> GRANT ALL PRIVILEGES ON *.* TO root% IDENTIFIED BY Root123 WITH GRANT OPTION; mysql> select host,user,authentication_string from user; -…

InnoDB的Buffer

一、Buffer内存结构 MySQL 服务器启动的时候就向操作系统申请了一片连续的内存&#xff0c;默认128M&#xff0c;可通过从参数修改。 [server] innodb_buffer_pool_size 268435456 1.1 控制块 控制块包括该页所属的 表空间编号、页号、缓存页在 Buffer Pool 中的地址、链表…

25.选择排序,归并排序,基数排序

目录 一. 选择排序 &#xff08;1&#xff09;简单选择排序 &#xff08;2&#xff09;堆排序 二. 归并排序 三. 基数排序 四. 各种排序方法的比较 &#xff08;1&#xff09;时间性能 &#xff08;2&#xff09;空间性能 &#xff08;3&#xff09;排序方法的稳定性能…

MyBatis查询数据库

文章目录 一.基础概念1.什么是MyBatis2.添加MyBatis依赖3.配置MyBatis中的xml路径 二.MyBatis的使用1.添加用户实体类2.添加 mapper 接⼝3.配置xml4.接口实现5.添加Service6.添加Controller 三.其它情况下Mybatis的使用1.返回自增主键值2.数据库字段和类属性不匹配 四.动态SQL1…

MybatisPlus-Generator

文章目录 一、前言二、MybatisPlus代码生成器1、引入依赖2、编写生成代码3、配置说明3.1、全局配置(GlobalConfig)3.2、包配置(PackageConfig)3.3、模板配置(TemplateConfig)3.4、策略配置(StrategyConfig)3.4.1、Entity 策略配置3.4.2、Controller 策略配置3.4.3、Service 策略…

Ceph IO流程及数据分布

1. Ceph IO流程及数据分布 1.1 正常IO流程图 步骤&#xff1a; client 创建cluster handler。client 读取配置文件。client 连接上monitor&#xff0c;获取集群map信息。client 读写io 根据crshmap 算法请求对应的主osd数据节点。主osd数据节点同时写入另外两个副本节点数据。…

C++ vector

目录 一、vector的介绍及使用 1.1 vector的介绍 1.1.1 认识vector 1.1.2 成员类型​​​​​​​ 1.1.3 成员函数一览 1.1.4 非成员函数重载 1.2 vector的使用 1.2.1 构造、析构与赋值操作符重载 1.2.2 reserve 与 resize 1.2.3 insert、erase 与 find extra train 1. 二叉树的…

工厂人员作业行为动作识别检测算法

工厂人员作业行为动作识别检测算法通过yolov7python深度学习算法框架模型&#xff0c;工厂人员作业行为动作识别检测算法实时识别并分析现场人员操作动作行为是否符合SOP安全规范流程作业标准&#xff0c;如果不符合则立即抓拍告警提醒。Python是一种由Guido van Rossum开发的通…

Nginx详解 三:高级配置

文章目录 1. 网页的状态页2. Nginx第三方模块2.1 echo模块 3. 变量3.1 内置变量3.1.1 示例 3.2 自定义变量3.2.1 自定义访问日志3.2.2 自定义json 格式日志 3.4 Nginx压缩功能 4. HTTPS4.1 Nginx的HTTPS工作原理4.2 启用功能模块的配置过程 5、自定义图标 1. 网页的状态页 基于…

【网络安全防护】上海道宁与Bitdefender帮助您构建弹性网络并降低安全运营成本

在网络的世界中 风险变得更加常见与复杂 企业需要从网络安全转向网络弹性 复杂的网络攻击已非常普遍 在面临攻击时 企业如何保持业务连续性&#xff1f; Bitdefender GravityZone将 风险分析、安全加固、威胁预防 检测和响应功能相结合 帮助您构建弹性网络 并降低安全…