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

news2025/4/23 14:59:23

进一步探讨如何使用 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 进行动态网页爬取,包括等待页面元素加载、处理无限滚动加载、单页应用的路由变化以及监听接口请求等常见场景

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

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

相关文章

数据结构——栈以及相应的操作

栈(Stack) 在维基百科中是这样定义的: 堆栈(stack) 又称为栈或堆叠,是计算机科学中的一种抽象资料类型,只允许在有序的线性资料集合中的一端(称为堆栈顶端,top)进行加入数据(push)和…

如何应对政策变化导致的项目风险

应对政策变化导致的项目风险,核心在于:加强政策研判机制、建立动态应对流程、构建合规应急预案、强化跨部门联动、提升项目柔性与调整能力。其中,加强政策研判机制 是所有防范工作中的“前哨哨兵”,可以让项目团队在政策风向转变之…

ASP.Net Web Api如何更改URL

1.找到appsettings.json 修改如下: 主要为urls的修改填本机私有地址即可 {"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": &q…

【HTTPS协议原理】数据加密、如何防止中间人攻击、证书和签名、HTTPS完整工作流程

⭐️个人主页:小羊 ⭐️所属专栏:Linux网络 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 数据加密常见的加密方式数据摘要方案一:仅使用对称加密方案二:仅使用非对称加密方案三:双…

Java中链表的深入了解及实现

一、链表 1.链表的概念 1.1链表是⼀种物理存储结构上⾮连续存储结构,数据元素的逻辑顺序是通过链表中的引⽤链接次序实现的 实际中链表的结构⾮常多样,以下情况组合起来就有8种链表结构: 2.链表的实现 1.⽆头单向⾮循环链表实现 链表中的…

植物大战僵尸杂交版v3.6最新版本(附下载链接)

B站游戏作者潜艇伟伟迷于4月19日更新了植物大战僵尸杂交版3.6版本!!!,有b站账户的记得要给作者三连关注一下呀! 不多废话下载链接放上: 夸克网盘链接::https://pan.quark.cn/s/1af9b…

【源码】【Java并发】【ThreadLocal】适合中学者体质的ThreadLocal源码阅读

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD 🔥 2025本人正在沉淀中… 博客更新速度 👍 欢迎点赞、收藏、关注,跟上我的更新节奏 📚欢迎订阅专栏…

背包问题模板

文章目录 01背包题意思路代码优化 完全背包题意思路代码优化 多重背包题意思路代码优化 分组背包题意思路代码 01背包 特点:每件物品最多只能用一次 01背包问题 题意 给出每件物品的体积v,价值w,求解能装入背包的的物品的最大价值,并且每件物品只能选一…

Sentinel源码—8.限流算法和设计模式总结二

大纲 1.关于限流的概述 2.高并发下的四大限流算法原理及实现 3.Sentinel使用的设计模式总结 3.Sentinel使用的设计模式总结 (1)责任链模式 (2)监听器模式 (3)适配器模式 (4)模版方法模式 (5)策略模式 (6)观察者模式 (1)责任链模式 一.责任链接口ProcessorSlot 二.责…

VulnHub-DarkHole_1靶机渗透教程

VulnHub-DarkHole_1靶机渗透教程 1.靶机部署 [Onepanda] Mik1ysomething 靶机下载:https://download.vulnhub.com/darkhole/DarkHole.zip 直接使用VMware打开就行 导入成功,打开虚拟机,到此虚拟机部署完成! 注意&#xff1a…

边缘计算全透视:架构、应用与未来图景

边缘计算全透视:架构、应用与未来图景 一、产生背景二、本质三、特点(一)位置靠近数据源(二)分布式架构(三)实时性要求高 四、关键技术(一)硬件技术(二&#…

MQ底层原理

RabbitMQ 概述 RabbitMQ 是⼀个开源的⾼性能、可扩展、消息中间件(Message Broker),实现了 Advanced Message Queuing Protocol(AMQP)协议,可以帮助不同应⽤程序之间进⾏通信和数据交换。RabbitMQ 是由 E…

本地部署DeepSeek-R1模型接入PyCharm

以下是DeepSeek-R1本地部署及接入PyCharm的详细步骤指南,整合了视频内容及官方文档核心要点: 一、本地部署DeepSeek-R1模型 1. 安装Ollama框架 ​下载安装包 访问Ollama官网(https://ollama.com/download)Windows用户选择.exe文件,macOS用户选择.dmg包。 ​安装验证 双击…

Java基于SpringBoot的企业车辆管理系统,附源码+文档说明

博主介绍:✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&…

进阶篇 第 2 篇:自相关性深度解析 - ACF 与 PACF 图完全指南

进阶篇 第 2 篇:自相关性深度解析 - ACF 与 PACF 图完全指南 (图片来源: Negative Space on Pexels) 欢迎来到进阶系列的第二篇!在上一篇,我们探讨了更高级的时间序列分解技术和强大的指数平滑 (ETS) 预测模型。ETS 模型通过巧妙的加权平均捕…

鸿蒙移动应用开发--渲染控制实验

任务:使用“对象数组”、“ForEach渲染”、“Badge角标组件”、“Grid布局”等相关知识,实现生效抽奖卡案例。如图1所示: 图1 生肖抽奖卡实例图 图1(a)中有6张生肖卡可以抽奖,每抽中一张,会通过弹层显示出来&#xf…

安宝特分享|AR智能装备赋能企业效率跃升

AR装备开启智能培训新时代 在智能制造与数字化转型浪潮下,传统培训体系正面临深度重构。安宝特基于工业级AR智能终端打造的培训系统,可助力企业构建智慧培训新生态。 AR技术在不同领域的助力 01远程指导方面 相较于传统视频教学的单向输出模式&#x…

SpringCloud组件—Eureka

一.背景 1.问题提出 我们在一个父项目下写了两个子项目,需要两个子项目之间相互调用。我们可以发送HTTP请求来获取我们想要的资源,具体实现的方法有很多,可以用HttpURLConnection、HttpClient、Okhttp、 RestTemplate等。 举个例子&#x…

模型 螃蟹效应

系列文章分享模型,了解更多👉 模型_思维模型目录。个体互钳,团队难行。 1 螃蟹效应的应用 1.1 教育行业—优秀教师遭集体举报 行业背景:某市重点中学推行绩效改革,将班级升学率与教师奖金直接挂钩,打破原…

符号速率估计——小波变换法

[TOC]符号速率估计——小波变换法 一、原理 1.Haar小波变换 小波变换在信号处理领域被成为数学显微镜,不同于傅里叶变换,小波变换可以观测信号随时间变换的频谱特征,因此,常用于时频分析。   当小波变换前后位置处于同一个码元…