Python爬取网页Flex渲染的动态内容

news2024/12/22 18:02:44

我最近使用Python爬取网页内容时遇到Flex渲染的动态页面,比如下图的课程目录标题,此时按鼠标右键,菜单里没有复制链接的选项。

目的:获取各个视频标题、链接。

按F12进入开发者模式分析网页,可见有多个flex标签,像这种通过flex动态渲染的网页,视频链接隐藏在JS代码里,需要人工点击才能运算出正确的链接,普通的requests库的get是无法直接获取的。

于是改变思路,尝试selenium的webdriver来打开浏览器,打开该网页,然后用find_element的By来搜索关键词“视频”,看看能不能定位到“视频”的元素:

from selenium import webdriver
from selenium.webdriver.common.by import By
options = webdriver.ChromeOptions()
# 关掉密码弹窗
options.add_experimental_option("prefs", prefs)
# 关闭提示“您的连接不是私密连接”
options.add_argument("--ignore-certificate-errors")
# 关闭提示“Chrome受自动控制提示”
options.add_experimental_option('useAutomationExtension', False) 
# 关闭提示“Chrome受自动控制提示”
options.add_experimental_option('excludeSwitches', ['enable-automation']) 
options.add_argument("--disable-extensions")
driver = webdriver.Chrome(options=options)

driver.get('......') # 打开网页url

l1=driver.find_element(By.PARTIAL_LINK_TEXT,'视频')
l2=driver.find_element(By.LINK_TEXT,'视频')

结果无论是l1还是l2,都会报错。

再尝试别的办法,如selenium的locate with:

from selenium.webdriver.support.relative_locator import locate_with, with_tag_name

l3=locate_with(By.LINK_TEXT, '视频')
l3.click()

l3=locate_with(...) 这一行通过了,但下一句l3.click()报错,提示没有click()的属性。

再想办法,改为:

l4=driver.find_element(l3)
l4.click()

但同样报错:selenium.common.exceptions.NoSuchElementException: Message: Cannot locate relative element with: {'link text': '视频'}

上面都使用了By.LINK_TEXT查找关键词来定位,是希望能精确定位,但在Flex渲染的页面里定位不了。

那么find_element改用By.CLASS_NAME又行不行?

l5=driver.find_element(By.CLASS_NAME,'item-title')
print(l5.text)

好!这下没有报错。结果返回l5的值是字符串:'一张图了解技术指标(上)'

接下来发送点击命令,如果顺利的话就通过driver.current_url获取播放视频页面的链接。

使用while 1循环,遍历查找所有class为“item-title”,直至查找报错,跳出循环。

links=[]
# 参考来源:https://blog.csdn.net/saber_sss/article/details/103460706
new_location=WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.CLASS_NAME,'item-title')))

while 1:    
    try:
        # 查询窗口总数,返回一个包含所有窗口句柄handles的列表
        handles=driver.window_handles 
        title=new_location.text # 获取视频标题
        new_location.click()
        # 对比一开始获取的窗口总数,确认新窗口出现了再去切换
        WebDriverWait(driver,5).until(EC.new_window_is_opened(handles))
        # 切换到新窗口
        handles=driver.window_handles #再次获取窗口句柄handles
        #执行切换窗口操作
        driver.switch_to.window(handles[-1])
        links.append([title, driver.current_url])
        # 关闭当前窗口
        driver.close()
        # 记得还要再切换去原来的窗口
        driver.switch_to.window(handles[0])
        last_location=new_location
        # 查找下一行
        new_location=driver.find_element(locate_with(By.CLASS_NAME,'item-title').below(last_location))
    except Exception:
        break

for i in links: print(i)

运行结果:

貌似成功了。但是对比原网页上的视频标题,获取的结果少了一半,find_element代码每次都隔行获取,为什么会隔行?离得太近了吗?

后来我到selenium的官网文档里查看关于locators的用法,发现除了below是查找下一行之外,还有“near”查找,于是把below改为near,结果却是查找到视频标题的第一行、第二行、第一行、第二行。。。如此循环。

为解决这个问题,只能先后处理查找奇数行、偶数行,最后合并奇、偶行结果并重新排序。

links=[]
l1=WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.CLASS_NAME,'item-title')))
l2=driver.find_element(locate_with(By.CLASS_NAME,'item-title').near(l1))
index=0
for locator in (l1,l2):
    while 1:    
        try:
            # 查询窗口总数,返回一个包含所有窗口句柄handles的列表
            handles=driver.window_handles 
            title=locator.text
            locator.click()
            # 对比一开始获取的窗口总数,确认新窗口出现了再去切换
            WebDriverWait(driver,5).until(EC.new_window_is_opened(handles))
            # 再次获取窗口句柄handles
            handles=driver.window_handles 
            # 新老句柄列表可以看出,新出现的句柄在列表里面排在后面
            # 执行切换窗口操作
            driver.switch_to.window(handles[-1])
            print(index, title, driver.current_url)
            links.append([index, title, driver.current_url])
            driver.close()
            # 记得还要切换回原来的窗口
            driver.switch_to.window(handles[0])
            locator=driver.find_element(locate_with(By.CLASS_NAME,'item-title').below(locator))
            # 为解决隔行,index加2
            index+=2
        except Exception:
            # 查找不到再多的元素就退出循环
            break
    # 然后处理偶数行,index设为1
    index=1
# 把结果重新排序
links=sorted(links)
for i in links: print(i)
driver.quit()

运行结果截图:

很不错!但还有一个bug:运行结果的第2、3项重复,估计是selenium的定位元素存在误差造成的。

参考来源:

【1】 爬虫实例(5)网页动态内容的识别_网页内容分类识别_演技拉满的白马的博客-CSDN博客

【2】浅谈selenium4新增功能之相对定位_the-ruffian的博客-CSDN博客_selenium相对定位法

【3】 python+selenium之窗口切换三种操作_saber_sss的博客-CSDN博客_python wd 切换窗口

【4】 Locator strategies | Selenium

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通用视觉框架OpenMMLab图像分类与基础视觉模型

文章目录流程传统方法:设计图像特征(1990s~2000s)特征工程的天花板从特征工程到特征学习层次化特征的实现方式AlexNet 的诞生& 深度学习时代的开始图像分类的数学表示AlexNet (2012)Going Deeper (2012~2014)VGG (2014)GoogLeNet (Inception v1, 2014)精度退化问…

ROS2 基础概念 动作

ROS2 基础概念 动作1. Actions2. 动作3. 中止目标4. 动作类型5. 动作请求1. Actions Actions 动作是ROS 2中的通信类型之一,适用于长时间运行的任务 它们由三部分组成:目标、反馈 和 结果,操作基于话题和服务 它们的功能类似于服务&#xff…

【大数据clickhouse】clickhouse 数据一致性保障常用解决方案

一、前言 对于任何一个数据存储的框架来说,确保数据的一致性都是其非常重要的组成部分,不管是过程中的强一致性,还是最终一致性,都是数据一致性的解决方案,本篇来聊聊clickhouse中的数据一致性问题。 二、clickhouse …

JMeter使用BeanShell断言

BeanShell简介BeanShell是使用Java语法的一套脚本语言,在JMeter的多种组件中都有BeanShell的身影,如:定时器:BeanShell Timer前置处理器:BeanShell PreProcessor采样器:BeanShell Sampler后置处理器&#x…

软件的生命周期(软件工程各阶段的工作)

其实软件工程是一个非常大的概念,我们的软件测试也好,软件开发也好,软件运维也好,其实都是属于软件工程的范畴。 今天就讲一讲软件工程和我们软件测试相关的一些内容。 我们今天三个主要的节点: 1.软件的生命周期 至…

QT中级(1)QTableView自定义委托(一)实现QSpinBox、QDoubleSpinBox委托

1 写在前面的话 我们在之前写的《QT(7)-初识委托》文章末尾提到,“使用一个类继承QStyledItemDelegate实现常用的控件委托,在使用时可以直接调用接口,灵活实现各种委托”。我们接下来几篇文章将先详细讲解各个控件的委托,最后整理…

怎么理解输入输出流 - 输入输出流之我解

背景 昨天领导开会,讨论两个接口之间参数问题,这个参数涉及文件传递的需求;其中一句话引起了我的思考:“参数怎么定义?能不能定义成字符流?” 当时我沉思了一下,懵的 没明白她的意思 我理解的比…

swagger2接口文档

文章目录简介Open APISwagger简介Spring-fox入门案例第一步:导入依赖第二步:编写controller类第三步:编写启动类第四步:运行启动类并访问ui页面Swagger UI 介绍基础信息配置自定义注解(防止有些类不生成接口文档&#…

数据结构:数组及特殊矩阵

数组及特殊矩阵一、认识数组1️⃣ 定义2️⃣ 存储结构1. 一维数组2. 二维数组二、特殊矩阵的压缩存储1️⃣ 对称矩阵💤思考1:有多少个二维元素A[0...n-1][0...n-1]存于一维元素中❓💤思考2:按行排列,二维数组A[0...n-1…

198分成功上岸浙江工业大学MBA的备考经验分享

我是2022年刚被浙江工业大学MBA项目录取的一名新生,新的一年管理类联考备考已经开始,最近身边有很多小伙伴也都在咨询这方面的信息,趁着今天有空给大家分享下我的经验。 在备考开始之前首先要确定目标,因为工作在杭州&#…

【正点原子Linux连载】第四章 SDK包的使用 摘自【正点原子】ATK-DLRV1126系统开发手册

1)实验平台:正点原子RV1126 Linux开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692176265749 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第四章 S…

学习周报-20230203

文章目录一 在rhel7系统使用Mariadb一 联系和区别二 需求三 部署安装3.1 环境准备3.2 安装软件包3.3 启动服务3.4 设置防火墙策略四 创建用户和库表4.1 登录数据库4.2 创建用户4.3 创建数据库和表五 备份和恢复5.1 备份 com 数据库5.2 模拟误删除操作5.3 恢复表二 使用grep忽略…

如何建立异形板框的内缩和外扩

如何建立异形板框的内缩和外扩 首先把需要内缩和外扩的外形图设置在信号层(比如TOP),把线宽改为0mil(方便计算)。然后选择外形图,执行命令TJ,就可以得到内缩和外扩图形。然后把生成的图形修改到…

Linux-查找文件、软链接、打包压缩和软件安装

查找文件find软链接ln打包和压缩tar软件安装apt-get1.查找文件find命令功能强大,通常用来在特定的目录下搜索符合条件的文件序号命令作用01find[路径] -name"*.py"查找指定路径下扩展名是.py的文件,包括子目录如果省略路径,表示在当…

最新整理Spring面试题2023

Spring面试专题 1.Spring应该很熟悉吧?来介绍下你的Spring的理解 有些同学可能会抢答,不熟悉!!! 好了,不开玩笑,面对这个问题我们应该怎么来回答呢?我们给大家梳理这个几个维度来回答 1.1 Spring的发展历程 先介绍…

【C++入门】引用详解(引用的特性、引用的使用、引用与指针的区别)

文章目录1 引用概念2 引用特性3 使用场景4 常引用5 传值与传引用的效率比较5.1 值和引用作为函数参数的性能比较5.2 值和引用作为返回值类型的性能比较6 引用和指针的区别1 引用概念 引用不是新定义一个变量,而是给已存在的变量取了一个别名,编译器不会为…

浅谈网络流

网络 网络是一张单向图 , 每条边都有一个权值 c(u,v)c(u,v)c(u,v) 表示边 (u,v)(u,v)(u,v) 的容量. 特别的 , 图上有源点 (s)(s)(s) 和汇点 (t)(t)(t). 网络流 在一张网络上 , 从源点流出 , 最终流入汇点的流. f(u,v)f(u,v)f(u,v) 表示 (u,v)(u,v)(u,v) 的流量. 满足 : 容…

【测试总结系列-1】质量保障之测试左移和右移

在开发一个系统或者说软件,需求分析、软件设计、程序编码、软件测试、运行维护,这些阶段必不可少。整个周期中,作为测试人员,不是只在测试阶段才能发挥作用,也不是仅有测试对软件质量负责,一个项目团队&…

关于图片上传和在页面显示问题

最近在工作中遇到一个关于图片上传的问题。根据之前项目的经验,我知道目前这个公司上传图片有两种方式, 一种是把图片上传到公司服务器上,然后把图片放在服务器上的地址存在数据库中,要获得图片的时候直接从库中拿地址就行了另一…

分析网络抓包用 python 更高效

Abstract分析网络抓包用 python 更高效AuthorsWalter FanCategorylearning noteStatusv1.0Updated2023-01-10LicenseCC-BY-NC-ND 4.0 网络抓包分析用的最多的两大工具是 tcpdump 和 wireshark. 一般我们通过 tcpdump 或者 wireshark 来捕获网络包为 *.pcap 或者 *.pcapng 文件 …