当前位置: 首页 > news >正文

JavaScript 渲染内容爬取实践:Puppeteer 进阶技巧

进一步探讨如何使用 Puppeteer 进行动态网页爬取,特别是如何等待页面元素加载完成、处理无限滚动加载、单页应用的路由变化以及监听接口等常见场景。

一、等待页面元素加载完成

在爬取动态网页时,确保页面元素完全加载是获取完整数据的关键。Puppeteer 提供了多种等待页面元素加载完成的方法。

1.1 使用 waitForSelector 方法

async function waitForElement() {const browser = await puppeteer.launch({ headless: true });const page = await browser.newPage();await page.goto('https://example.com');await page.waitForSelector('selector-of-element'); // 替换为实际的 CSS 选择器console.log('元素加载完成');// 提取元素内容const content = await page.$eval('selector-of-element', el => el.textContent);console.log('元素内容:', content);await browser.close();
}waitForElement();

1.2 使用 waitForXPath 方法

async function waitForXPathElement() {const browser = await puppeteer.launch({ headless: true });const page = await browser.newPage();await page.goto('https://example.com');await page.waitForXPath('//*[@id="element-id"]'); // 替换为实际的 XPath 表达式console.log('元素加载完成');// 提取元素内容const content = await page.evaluate(() => {return document.evaluate('//*[@id="element-id"]', document).iterateNext().textContent;});console.log('元素内容:', content);await browser.close();
}waitForXPathElement();

二、处理无限滚动加载

无限滚动加载是一种常见的动态网页加载方式,通过监听滚动事件动态加载更多内容。可以使用 Puppeteer 模拟滚动操作,获取所有内容。

async function handleInfiniteScroll() {const browser = await puppeteer.launch({ headless: true });const page = await browser.newPage();await page.goto('https://example.com/infinite-scroll-page');// 设置页面高度,模拟无限滚动const prevPageHeight = await page.evaluate('document.body.scrollHeight');let newPageHeight;while (true) {await page.evaluate(() => {window.scrollTo(0, document.body.scrollHeight);});await page.waitForTimeout(2000); // 等待内容加载newPageHeight = await page.evaluate('document.body.scrollHeight');if (newPageHeight === prevPageHeight) {break; // 如果页面高度不再变化,退出循环}prevPageHeight = newPageHeight;}// 提取内容const contentList = await page.evaluate(() => {return Array.from(document.querySelectorAll('selector-of-content-item')).map(item => item.textContent);});console.log('内容列表:', contentList);await browser.close();
}handleInfiniteScroll();

三、单页应用的路由变化处理

单页应用(SPA)通常通过 JavaScript 动态更新页面内容而不重新加载整个页面。可以使用 Puppeteer 监听路由变化,获取不同路由下的内容。

async function handleSpaRouteChanges() {const browser = await puppeteer.launch({ headless: true });const page = await browser.newPage();await page.goto('https://example.com/spa-page');// 监听路由变化page.on('response', async (response) => {if (response.url().includes('api/new-route')) {console.log('路由变化检测到,获取新内容');// 提取新路由下的内容const content = await page.evaluate(() => {return document.querySelector('selector-of-new-route-content').textContent;});console.log('新路由内容:', content);}});// 触发路由变化的操作await page.click('selector-of-route-link');await browser.close();
}handleSpaRouteChanges();

四、监听接口请求

在某些情况下,我们可能需要监听特定的接口请求,获取接口返回的数据。Puppeteer 提供了监听网络请求的功能。

async function listenApiRequest() {const browser = await puppeteer.launch({ headless: true });const page = await browser.newPage();// 监听网络请求page.on('response', async (response) => {const url = response.url();if (url.includes('api/data')) { // 监听特定接口try {const data = await response.json(); // 获取接口返回的 JSON 数据console.log('接口数据:', data);} catch (error) {console.error('解析接口数据出错:', error);}}});await page.goto('https://example.com/page-with-api-calls');// 执行触发接口请求的操作await page.click('selector-of-api-call-trigger');await browser.close();
}listenApiRequest();

五、完整示例:爬取动态电商网站

以下是一个完整的示例,演示如何使用 Puppeteer 爬取一个动态电商网站的商品列表,该网站使用无限滚动加载商品内容。

async function scrapeEcommerceProducts() {const browser = await puppeteer.launch({ headless: true });const page = await browser.newPage();await page.goto('https://example.com/products', { waitUntil: 'networkidle2' });// 设置页面高度,模拟无限滚动const prevPageHeight = await page.evaluate('document.body.scrollHeight');let newPageHeight;const productSet = new Set(); // 使用集合避免重复while (true) {// 提取当前页面的商品内容const products = await page.evaluate(() => {return Array.from(document.querySelectorAll('.product-item')).map(item => {return {title: item.querySelector('.product-title').textContent,price: item.querySelector('.product-price').textContent};});});// 将商品信息添加到集合products.forEach(product => productSet.add(JSON.stringify(product)));// 滚动页面await page.evaluate(() => {window.scrollTo(0, document.body.scrollHeight);});await page.waitForTimeout(2000); // 等待内容加载newPageHeight = await page.evaluate('document.body.scrollHeight');if (newPageHeight === prevPageHeight) {break; // 如果页面高度不再变化,退出循环}prevPageHeight = newPageHeight;}// 将集合转换为数组并输出const productList = Array.from(productSet).map(item => JSON.parse(item));console.log('商品列表:', productList);await browser.close();
}scrapeEcommerceProducts();

六、总结

通过本文的案例和实践,深入探讨了如何使用 Puppeteer 进行动态网页爬取,包括等待页面元素加载、处理无限滚动加载、单页应用的路由变化以及监听接口请求等常见场景

相关文章:

JavaScript 渲染内容爬取实践:Puppeteer 进阶技巧

进一步探讨如何使用 Puppeteer 进行动态网页爬取,特别是如何等待页面元素加载完成、处理无限滚动加载、单页应用的路由变化以及监听接口等常见场景。 一、等待页面元素加载完成 在爬取动态网页时,确保页面元素完全加载是获取完整数据的关键。Puppeteer…...

AI数字人:元宇宙舞台上的闪耀新星(7/10)

摘要:AI数字人作为元宇宙核心角色,提升交互体验,推动内容生产变革,助力产业数字化转型。其应用场景涵盖虚拟社交、智能客服、教育、商业营销等,面临技术瓶颈与行业规范缺失等挑战,未来有望突破技术限制&…...

测试基础笔记第九天

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、数据类型和约束1.数据类型2.约束3.主键4.不为空5.唯一6.默认值 二、数据库操作1.创建数据库2.使用数据库3.修改数据库4.删除数据库和查看所有数据库5.重点&…...

C++抽象基类定义与使用

在 C 中,抽象基类(Abstract Base Class, ABC) 是一种特殊的类,用于定义接口规范和约束派生类的行为。它通过纯虚函数(Pure Virtual Function)强制要求派生类实现特定功能,自身不能被实例化。以下…...

20.4 显示数据库数据

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的 20.4.1 设计时进行简单绑定 【例 20.22】【项目:code20-022】设计时关联数据库。 设计时设置DataGridView的DataSource属…...

PyTorch 多 GPU 入门:深入解析 nn.DataParallel 的工作原理与局限

当你发现单个 GPU 已经无法满足你训练庞大模型或处理海量数据的需求时,利用多 GPU 进行并行训练就成了自然的选择。PyTorch 提供了几种实现方式,其中 torch.nn.DataParallel (简称 DP) 因其使用的便捷性,常常是初学者接触多 GPU 训练的第一站…...

UDP协议理解

文章目录 UDP协议理解UDP 协议的特点:UDP协议图示UDP 的头部结构:UDP数据传输图示 UDP 的应用场景:TCP 与UDP对比UDP的传输丢包和顺序错乱问题(了解)丢包的解决方法:顺序错乱的解决方法:综合应用…...

微信小程序拖拽排序有效果图

效果图 .wxml <view class"container" style"--w:{{w}}px;" wx:if"{{location.length}}"><view class"container-item" wx:for"{{list}}" wx:key"index" data-index"{{index}}"style"--…...

算力网络的早期有关论文——自用笔记

2023年底至2024年初阅读有关论文的自用笔记&#xff0c;作为参考。 算力网络架构 https://baijiahao.baidu.com/s?id1727377583404975414&wfrspider&forpc think&note 是否可以和cpu进程调度联系。 目前&#xff1a;看一些综述深一步了解背景和发展现状,完善认…...

卷积神经网络基础(四)

今天我们继续学习各个激活函数层的实现过程。 目录 5.2 Sigmoid层 六、Affine/Softmax层实现 6.1 Affine层 6.2 批处理版本 5.2 Sigmoid层 sigmoid函数的表达式如下&#xff1a; 用计算图表示的话如下&#xff1a; 计算过程稍微有些复杂&#xff0c;且这里除了乘法和加法…...

【MySQL数据库】表的约束

目录 1&#xff0c;空属性 2&#xff0c;默认值 3&#xff0c;列描述 4&#xff0c;zerofill 5&#xff0c;主键primary key 6&#xff0c;自增长auto_increment 7&#xff0c;唯一键unique 8&#xff0c;外键foreign key 在MySQL中&#xff0c;表的约束是指用于插入的…...

网络威胁情报 | Friday Overtime Trooper

本文将分别从两个环境出发&#xff0c;以实践来体验利用威胁情报分析可疑文件的过程。 Friday Overtime 现在你是一位安全分析人员&#xff0c;正在美美等待周五过去&#xff0c;但就在即将下班之时意外发生了&#xff1a;你的客户发来求助&#xff0c;说他们发现了一些可疑文…...

GPIO(通用输入输出端口)详细介绍

一、基本概念 GPIO&#xff08;General - Purpose Input/Output&#xff09;即通用输入输出端口&#xff0c;是微控制器&#xff08;如 STM32 系列&#xff09;中非常重要的一个外设。它是一种软件可编程的引脚&#xff0c;用户能够通过编程来控制这些引脚的输入或输出状态。在…...

学习笔记——《Java面向对象程序设计》-继承

参考教材&#xff1a; Java面向对象程序设计&#xff08;第3版&#xff09;微课视频版 清华大学出版社 1、定义子类 class 子类名 extends 父类名{...... }如&#xff1a; class Student extends People{...... } &#xff08;1&#xff09;如果一个类的声明中没有extends关…...

基于javaweb的SpringBoot校园失物招领系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...

什么事Nginx,及使用Nginx部署vue项目(非服务器Nginx压缩包版)

什么是 Nginx? Nginx(发音为 “engine-x”)是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。它以其高性能、高并发处理能力和低资源消耗而闻名。以下是 Nginx 的主要特性和用途: 主要特性 高性能和高并发 Nginx 能够处理大量并发连接,适合高…...

nodejs使用require导入npm包,开发依赖和生产依赖 ,全局安装

nodejs使用require导入npm包&#xff0c;开发依赖和生产依赖 &#xff0c;全局安装 ✅ 一、Node.js 中使用 require() 导入 npm 包 // 导入第三方包&#xff08;例如 axios&#xff09; const axios require(axios);// 使用 axios.get(https://api.example.com).then(res &g…...

CSS在线格式化 - 加菲工具

CSS在线格式化 打开网站 加菲工具 选择“CSS在线格式化” 或者直接访问 https://www.orcc.top/tools/css 输入CSS代码&#xff0c;点击左上角的“格式化”按钮 得到格式化后的结果...

图片转base64 - 加菲工具 - 在线转换

图片转base64 - 加菲工具 先进入“加菲工具” 网 打开 https://www.orcc.top&#xff0c; 选择 “图片转base64”功能 选择需要转换的图片 复制 点击“复制”按钮&#xff0c;即可复制转换好的base64编码数据&#xff0c;可以直接用于img标签。...

性能比拼: Redis vs Dragonfly

本内容是对知名性能评测博主 Anton Putra Redis vs Dragonfly Performance (Latency - Throughput - Saturation) 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 在本视频中&#xff0c;我们将对比 Redis 和 Dragonfly。我们将观察 set 与 get 操作的延迟&#xff…...

如何收集用户白屏/长时间无响应/接口超时问题

想象一下这样的场景:一位用户在午休时间打开某电商应用,准备购买一件心仪已久的商品。然而,页面加载了数秒后依然是一片空白,或者点击“加入购物车”按钮后没有任何反馈,甚至在结算时接口超时导致订单失败。用户的耐心被迅速消耗殆尽,关闭应用,转而选择了竞争对手的产品…...

来啦,烫,查询达梦表占用空间

想象一下oracle&#xff0c;可以查dba_segments&#xff0c;但是这个不可靠&#xff08;达梦官方连说明书都没有&#xff09; 先拼接一个sql set lineshow off SELECT SELECT ||||OWNER|||| AS OWNER,||||TABLE_NAME|||| AS TABLE_NAME,TABLE_USED_SPACE(||||OWNER||||,||||T…...

# 利用迁移学习优化食物分类模型:基于ResNet18的实践

利用迁移学习优化食物分类模型&#xff1a;基于ResNet18的实践 在深度学习的众多应用中&#xff0c;图像分类一直是一个热门且具有挑战性的领域。随着研究的深入&#xff0c;我们发现利用预训练模型进行迁移学习是一种非常有效的策略&#xff0c;可以显著提高模型的性能&#…...

AT24C02芯片简介:小巧强大的串行EEPROM存储器

一、AT24C02概述 AT24C02是一款2K位&#xff08;即256字节&#xff09;的串行EEPROM芯片&#xff0c;采用IC&#xff08;Inter-Integrated Circuit&#xff09;总线进行通信&#xff0c;适合低功耗、小容量存储需求。 主要特性&#xff1a; 项目 参数 存储容量 2Kb&#x…...

【Vue】状态管理(Vuex、Pinia)

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Vue 文章目录 1. 状态管理概述1.1 什么是状态管理1.2 为什么需要状态管理 2. Vuex基础2.1 Vuex核心概念2.1.1 State2.1.2 Getters2.1.3 Mutations2.1.4 Actions2.1.5 Modules 2.2 Vuex辅助函数2.2.1 mapState2.2.2 mapGetters2.…...

施磊老师基于muduo网络库的集群聊天服务器(四)

文章目录 实现登录业务登录业务代码补全数据库接口:查询,更新状态注意学习一下里面用到的数据库api测试与问题**问题1:****问题2:** 用户连接信息与线程安全聊天服务器是长连接服务器如何找到用户B的连接&#xff1f;在业务层存储用户的连接信息多线程安全问题加锁! 处理客户端…...

深度学习-全连接神经网络(过拟合,欠拟合。批量标准化)

七、过拟合与欠拟合 在训练深层神经网络时&#xff0c;由于模型参数较多&#xff0c;在数据量不足时很容易过拟合。而正则化技术主要就是用于防止过拟合&#xff0c;提升模型的泛化能力(对新数据表现良好)和鲁棒性&#xff08;对异常数据表现良好&#xff09;。 1. 概念认知 …...

访问Maven私服的教程

1.首先准备好maven私服的启动器&#xff0c;到bin目录下启动&#xff1a; 2.等待加载&#xff0c;加载过程比较长: 3.访问端口号: 4.仓库简介: 5.在maven的setting中 servers配置信息(设置私服访问的密码): 6.配置私服仓库地址: 7.配置上传地址(私服地址): 8.在自己的副项…...

Linux系统编程 day9 SIGCHLD and 线程

SIGCHLD信号 只要子进程信号发生改变&#xff0c;就会产生SIGCHLD信号。 借助SIGCHLD信号回收子进程 回收子进程只跟父进程有关。如果不使用循环回收多个子进程&#xff0c;会产生多个僵尸进程&#xff0c;原因是因为这个信号不会循环等待。 #include<stdio.h> #incl…...

Linux 内核中 cgroup 子系统 cpuset 是什么?

cpuset 是 Linux 内核中 cgroup&#xff08;控制组&#xff09; 的一个子系统&#xff0c;用于将一组进程&#xff08;或任务&#xff09;绑定到特定的 CPU 核心和 内存节点&#xff08;NUMA 节点&#xff09;上运行。它通过限制进程的 CPU 和内存资源的使用范围&#xff0c;优…...

乐视系列玩机---乐视2 x520 x528等系列线刷救砖以及刷写第三方twrp 卡刷第三方固件步骤解析

乐视2 x520 x528 x526等,搭载了高通骁龙652处理器,骁龙652的GPU性能甚至优于前一年的骁龙810,配备了3GB RAM和32GB ROM的存储空间, 通过博文了解💝💝💝 1💝💝💝-----详细解析乐视2 x520系列黑砖线刷救砖的步骤 2💝💝💝----官方两种更新卡刷步骤以及刷…...

电容加速电路!

大家好&#xff0c;我是记得诚。 今天分享一个小电路&#xff1a;电容加速电路。 下面是一个普通的三极管开关电路&#xff0c;区别是多了一个C1&#xff0c;C1被称为加速电容。作用是&#xff1a;加速三极管VT1的开通和截止&#xff0c;做到快开快关。 工作原理&#xff1a;…...

MCP Host、MCP Client、MCP Server全流程实战

目录 准备工作 MCP Server 实现 调试工作 MCP Client 实现 MCP Host 配置 第一步:配置支持 function calling的 LLM 第二步:添加MCP Server 一般有两种方式,第一种json配置,第二种直接是Command形式,我这里采用Command形式 第三步:使用MCP Server 准备工作 安装…...

Win10一体机(MES电脑设置上电自动开机)

找个键盘&#xff0c;带线的那种&#xff0c;插到电脑上&#xff0c;电脑开机&#xff1b;连续点按F11&#xff1b;通过↑↓键选择Enter Setup 然后回车&#xff1b; 选择 smart settings &#xff1b; 选择 Restore AC Power Loss By IO 回车&#xff1b; 将prower off 改为…...

强化学习和微调 区别如下

强化学习和微调 区别如下 定义与概念 强化学习**:是一种机器学习范式,强调智能体(agent)如何在环境中采取一系列行动,以最大化累积奖励**。智能体通过与环境进行交互,根据环境反馈的奖励信号来学习最优的行为策略。例如,机器人通过不断尝试不同的动作来学习如何在复杂环…...

【EasyPan】文件上传、文件秒传、文件转码、文件合并、异步转码、视频切割分析

【EasyPan】项目常见问题解答&#xff08;自用&持续更新中…&#xff09;汇总版 文件上传方法解析 一、方法总览 Transactional(rollbackFor Exception.class) public UploadResultDto uploadFile(...)核心能力&#xff1a; 秒传验证&#xff1a;通过MD5文件大小实现文…...

React18+ 项目搭建-从初始化、技术选型到开发部署的全流程规划

搭建一个 React 项目需要从项目初始化、技术选型到开发部署的全流程规划。以下是详细步骤和推荐的技术栈&#xff1a; 一、项目初始化 1. 选择脚手架工具 推荐工具&#xff1a; Vite&#xff08;现代轻量级工具&#xff0c;支持 React 模板&#xff0c;速度快&#xff09;&am…...

day3 打卡训练营

循环语句和判断语句之前已经会了&#xff0c;把列表的方法练一练 浙大疏锦行 python训练营介绍...

MySQL VS SQL Server:优缺点全解析

数据库选型、企业协作、技术生态、云数据库 1.1 MySQL优缺点分析 优点 开源免费 社区版完全免费&#xff0c;适合预算有限的企业 允许修改源码定制功能&#xff08;需遵守GPL协议&#xff09; 跨平台兼容性 支持Windows/Linux/macOS&#xff0c;适配混合环境部署 云服务商…...

【CPP】固定大小内存池

程序运行时&#xff0c;通常会频繁地进行内存的分配和释放操作。传统的内存分配方式&#xff08;如使用new和delete运算符&#xff09;可能会导致内存碎片的产生&#xff0c;并且每次分配和释放内存都有一定的时间开销。内存池通过在程序启动时一次性分配一大块内存或一次性分配…...

[数据结构]树和二叉树

概念 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次关系的集合。 树形结构中&#xff0c;子树之间不能有交集&#xff0c;否则就不是树形结构 双亲结点或父结点 &#xff1a;若一个结点含有子结点&#xff0c;则…...

监控页面卡顿PerformanceObserver

监控页面卡顿PerformanceObserver 性能观察器掘金 const observer new PerformanceObserver((list) > {}); observer.observe({entryTypes: [longtask], })...

Web开发-JavaEE应用JNDI注入RMI服务LDAP服务DNS服务高版本限制绕过

知识点&#xff1a; 1、安全开发-JavaEE-JNDI注入-LADP&RMI&DNS等 2、安全开发-JavaEE-JNDI注入-项目工具&手工原理等 演示案例-WEB开发-JavaEE-JNDI注入&LDAP&RMI服务&DNS服务&高版本限制绕过 JNDI全称为 Java Naming and DirectoryInterface&am…...

深度学习训练中的显存溢出问题分析与优化:以UNet图像去噪为例

最近在训练一个基于 Tiny-UNet 的图像去噪模型时&#xff0c;我遇到了经典但棘手的错误&#xff1a; RuntimeError: CUDA out of memory。本文记录了我如何从复现、分析&#xff0c;到逐步优化并成功解决该问题的全过程&#xff0c;希望对深度学习开发者有所借鉴。 训练数据&am…...

【Spring】单例模式的创建方式(Bean解析)

在Java中&#xff0c;单例模式&#xff08;Singleton Pattern&#xff09;确保一个类只有一个实例&#xff0c;并提供全局访问点。以下是实现单例的五种常见方式&#xff1a;懒汉式、饿汉式、双重检查锁、静态内部类和枚举&#xff0c;包括代码示例和优缺点分析。 1. 懒汉式&am…...

小小矩阵设计

在电气设计图中&#xff0c;矩阵设计的接线方法是通过结构化布局实现多灵活链接的技术&#xff0c;常用于信号切换、配电调压或更加复杂的控制场景。 今天聊一种在电气图纸中用到的一种简单矩阵接法&#xff0c;一眼就看明白&#xff0c;很大程度简化了程序控制点和继电器的使用…...

IOT项目——双轴追光系统

双轴太阳能追光系统 - ESP32实现 系统概述 这个系统使用&#xff1a; ESP32开发板2个舵机&#xff08;水平方向和垂直方向&#xff09;4个光敏电阻&#xff08;用于检测光照方向&#xff09;适当的电阻&#xff08;用于光敏电阻分压&#xff09; 接线示意图 --------------…...

深度学习基石:神经网络核心知识全解析(一)

神经网络核心知识全解析 一、神经网络概述 神经网络作为机器学习领域的关键算法&#xff0c;在现代生活中发挥着重要作用&#xff0c;广泛应用于图像识别、语音处理、智能推荐等诸多领域&#xff0c;深刻影响着人们的日常生活。它通过模拟人类大脑神经系统的结构和功能&#…...

什么是 金字塔缩放(Multi-scale Input)

金字塔缩放 什么是金字塔缩放(Multi-scale Input)什么场景下会用到金字塔缩放?图像识别目标跟踪图像压缩视频处理如何在计算机程序中实现金字塔缩放?准备数据缩小数据(构建金字塔的上层)存储数据使用数据(在程序中应用金字塔缩放)金字塔缩放的记忆卡片什么是金字塔缩放(M…...

从零开始配置 Zabbix 数据库监控:MySQL 实战指南

Zabbix作为一款开源的分布式监控工具&#xff0c;在监控MySQL数据库方面具有显著优势&#xff0c;能够为数据库的稳定运行、性能优化和故障排查提供全面支持。以下是使用Zabbix监控MySQL数据库的配置。 一、安装 Zabbix Agent 和 MySQL 1. 安装 Zabbix Agent services:zabbix…...