百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Python的selenium实现等待某个元素加载完成后返回结果

bigegpt 2025-03-18 19:58 6 浏览

1. 介绍

1.1 介绍

福哥在使用selenium的时候遇到了一个问题,就是页面有些元素和数据是通过AJAX渲染的,而且采用的是异步加载的方式实现的AJAX功能,这样在selenium认为页面已经加载完成了的时候其实数据还没有渲染上,这个可愁坏福哥了!

经过研究发现selenium有两个功能就是可以实现福哥想要的效果,一个是WebDriverWait对象,另一个是implicitly_wait方法,它们都可以达到建立一个监视器,等待元素加载到页面上之后立即捕获并返回的目的。

另外福哥还发现使用time对象的sleep方法也可以实现这个效果,而且自由度非常高,特别适合处理复杂的情况。

这些技巧大家跟着福哥来一起学习一下吧~~

2. AJAX页面

福哥弄了一个AJAX异步延迟渲染的页面,保证正常情况下selenium绝对无法获得渲染后的内容,拿这个来做实验!

2.1 直接爬取

使用下面的代码直接爬取页面,很显然异步延迟的AJAX渲染的数据是拿不到的。

chrome.get("http://192.168.2.168/tfams/test.html")
print(chrome.find_element_by_css_selector("p#content-in-ajax").text)

3. WebDriverWait

使用WebDriverWait对象来实现等待元素加载完毕的监视是一个比较理想的方法,我们可以设置一个最长等待时间,然后通过EC对象的presence_of_element_located方法进行预期元素的查找尝试,如果查找成功那么WebDriverWait的until方法就会立即返回,否则的话WebDriverWait的until方法会在达到最长等待时间之前一直等待着,超过最长等待时间的时候就会抛出异常错误。

看完WebDriverWait的工作原理之后,福哥惊呼这不就是我们想要的东西吗?

3.1 安装

需要引入三个库,都是selenium.webdriver下面的库。

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

3.2 示例

这是一个使用WebDriverWait实现等待AJAX加载完毕的示例。

chrome.get("http://192.168.2.168/tfams/test.html")
try:
    WebDriverWait(chrome, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "p#content-in-ajax h3")))
except Exception as e:
    doNothing = e
print(chrome.find_element_by_css_selector("p#content-in-ajax").text)

看!这下内容爬取到了哦~~

因为示例当中的p标签的内容来自AJAX,而内容是复合型的HTML结构,我们无法判断p标签是否为空,只能抓p标签下面的一个子元素h3作为加载完毕的标志,再去取整个p标签了!

4. implicitly_wait

使用implicitly_wait方法来实现等待元素加载完毕也还可以,在通过implicitly_wait设置了等待时间之后,每一次通过find_xxx方法查找元素的时候都会进行查找尝试,并且在最长等待时间之前查找成功就可以。

也就是说,我们在设置了implicitly_wait之后再去调用find_xxx方法去查找元素的时候,如果元素没有找到find_xxx并不会返回None而是反复进行查找尝试,在通过implicitly_wait设置的最长等待时间到达之前查找成功就会立即返回,超过了通过implicitly_wait设置的最长等待时间的时候就会抛出异常错误。

4.1 示例

这是一个使用implicitly_wait实现等待AJAX加载完毕的示例。

chrome.implicitly_wait(10)
chrome.get("http://192.168.2.168/tfams/test.html")
try:
    chrome.find_element_by_css_selector("p#content-in-ajax h3")
except Exception as e:
    doNothing = e
print(chrome.find_element_by_css_selector("p#content-in-ajax").text)

看!这样也可以爬取到哦~~

因为示例当中的p标签的内容来自AJAX,而内容是复合型的HTML结构,我们无法判断p标签是否为空,只能抓p标签下面的一个子元素h3作为加载完毕的标志,再去取整个p标签了!

5. time.sleep

最后一个是使用time对象的sleep方法进行人工延迟,具体实现方法是通过循环语句进行计时,并且在每次循环里手动检查结果是否完成,如果结果完成了就跳出。

网上说这是最蠢的方案,福哥并不认同这个观点。

在实际的项目当中,如果场景是AJAX程序处理完毕后会动态渲染出一个元素出来,这种情况当然可以使用WebDriverWait对象或者implicitly_wait方法进行查找。但是,假如场景是AJAX程序处理完毕后会动态删除一个元素,又或是改变一个元素的属性、样式,那么通过WebDriverWait对象或者implicitly_wait方法就不灵了。

不过,这种情况下使用time.sleep却可以解决,因为我们可以用最原始的方式,每次计时循环通过execute_script方法去检查元素是不是被删除了,又或是通过execute_script方法去检查元素的属性、样式是不是改变了,这样就可以解决问题了!

5.1 安装

使用time.sleep需要导入time库,这个是系统自带的库,不需要单独安装。

import time

5.2 示例1

这是一个使用time.sleep实现等待AJAX加载完毕的示例。

chrome.get("http://192.168.2.168/tfams/test.html")
waitSecs = 10
while waitSecs > 0:
    try:
        chrome.find_element_by_css_selector("p#content-in-ajax h3")
        break
    except Exception as e:
        doNothing = e
    waitSecs = waitSecs-1
    time.sleep(1)
print(chrome.find_element_by_css_selector("p#content-in-ajax").text)

代码有点复杂是不是?没有关系,下面福哥再来一个只有time.sleep可以干的事情的例子。

5.3 示例2

这是一个使用time.sleep实现等待AJAX加载完毕的示例,条件是不能预判AJAX加载的内容包含什么元素,也就是说我们不能再去判断p标签下面有没有h3标签了。

这下可怎么办呢?

chrome.get("http://192.168.2.168/tfams/test.html")
waitSecs = 10
while waitSecs > 0:
    isEmptyTagP = chrome.execute_script("return $.trim($('p#content-in-ajax').text()) == '' ? true : false;")
    if isEmptyTagP == False:
        break
    waitSecs = waitSecs-1
    time.sleep(1)
print(chrome.find_element_by_css_selector("p#content-in-ajax").text)

看到了吗?福哥自定义了一个逻辑,在当前页面执行JS脚本判断p标签下面是不是空的,如果不是空的就证明AJAX渲染完成了,这个过程完全不需要知道AJAX会加载什么内容出来都可以实现。

6. 总结

今天大家跟着福哥学会了在使用selenium抓取网页的时候,可以根据自己的情况在AJAX异步渲染的某个元素加载完成之后再返回结果,这样可以实现准确地判断那些异步加载数据的页面的加载完成时间,获得我们预期的结果。


https://m.tongfu.net/home/35/blog/513255.html

相关推荐

【机器学习】数据挖掘神器LightGBM详解(附代码)

来源:机器学习初学者本文约11000字,建议阅读20分钟本文为你介绍数据挖掘神器LightGBM。LightGBM是微软开发的boosting集成模型,和XGBoost一样是对GBDT...

3分钟,用DeepSeek全自动生成语音计算器,还带括号表达式!

最近,大家慢慢了解到了DeepSeek的强大功能,特别是它在编程领域也同样强大。编程零基础小白,一行代码不用写,也能全自动生成一个完整的、可运行的软件来!很多程序员一直不相信小白不写代码也能编软件!下...

python学习笔记 3.表达式

在Python中,表达式是由值、变量和运算符组成的组合。以下是一些常见的Python表达式:算术表达式:由数值和算术运算符组成的表达式,如加减乘除等。例如:5+3、7*2、10/3等。字符...

5.7 VS 8.x,为什么用户不升级MySql

一般来说为了更好的功能和性能,都需要将软件升级到最新的版本,然而在开源软件中,由于一些开发商变化或其他的问题(开源授权变化),致使人们不愿使用最新的版本,一个最典型的问题就是CentOS操作系统。还有...

大厂高频:讲一下MySQL主从复制

大家经常听说主从复制,那么主从复制的意义?能解决的问题有哪些?主从复制能解决的问题就是在我们平时开发的程序中操作数据库的时候,大多数的情况查询的操作大大超过了写的操作,也就说对数据库读取数据的压力比较...

MYSQL数据库的五大安全防护措施

以技术为基础的企业里最有价值的资产莫过于是客户或者其数据库中的产品信息了。因此,在这样的企业中,保证数据库免受外界攻击是数据库管理的重要环节。很多数据库管理员并没有实施什么数据库保护措施,只是因为觉得...

docker安装mysql

准备工作已安装Docker环境(官方安装文档)终端/命令行工具(Linux/macOS/WSL)步骤1:拉取MySQL镜像打开终端执行以下命令,拉取官方MySQL镜像(默认最新版本):d...

Zabbix监控系统系列之六:监控 mysql

zabbix监控mysql1、监控规划在创建监控项之前要尽量考虑清楚要监控什么,怎么监控,监控数据如何存储,监控数据如何展现,如何处理报警等。要进行监控的系统规划需要对Zabbix很了解,这里只是...

详解MySQL的配置文件及优化

#头条创作挑战赛#在Windows系统中,MySQL服务器启动时最先读取的是my.ini这个配置文件。在Linux系统中,配置文件为my.cnf,其路径一般为/etc/my.cnf或/etc/mysq...

Mysql 几个批处理执行脚本

学习mysql过程中,需要创建测试数据,并让多人每人一个数据库连接并进行作业检查。整合部分批处理创建数据批量创建数据库DELIMITER$CREATEPROCEDURECreateDatab...

MySQL学到什么程度?才有可以在简历上写精通

前言如今互联网行业用的最多就是MySQL,然而对于高级Web面试者,尤其对于寻找30k下工作的求职者,很多MySQL相关知识点基本都会涉及,如果面试中,你的相关知识答的模糊和不切要点,基...

mysql 主、从服务器配置“Slave_IO_Running: Connecting” 问题分析

#在进行mysql主、从服务器配置时,”SHOWSLAVESTATUS;“查看从库状态Slave_IO_Runing,出现错误:“Slave_IO_Running:Connectin...

MYSQL数据同步

java开发工程师在实际的开发经常会需要实现两台不同机器上的MySQL数据库的数据同步,要解决这个问题不难,无非就是mysql数据库的数据同步问题。但要看你是一次性的数据同步需求,还是定时数据同步,亦...

「MySQL 8」MySQL 5.7都即将停只维护了,是时候学习一波MySQL 8了

MySQL8新特性选择MySQL8的背景:MySQL5.6已经停止版本更新了,对于MySQL5.7版本,其将于2023年10月31日停止支持。后续官方将不再进行后续的代码维护。另外,...

Prometheus监控mysql

通过Prometheus监控Mysql,我们需要在Mysql端安装一个mysql-exporter,然后Prometheus通过mysql-exporter暴露的端口抓取数据。1.安装一个MYSQL配...