Puppeteer监听网络请求、爬取网页图片(二)

news2024/11/27 2:37:35

Puppeteer监听网络请求、爬取网页图片(二)

在这里插入图片描述

    • Puppeteer监听网络请求、爬取网页图片(二)
        • 一、爬取需求
        • 二、实现讲解
        • 三、效果查看

一、爬取需求
  • 首先打开浏览器,打开指定网站
  • 监听网站发出的所有请求,记录请求,将请求存储到文件中
  • 屏蔽网页中出现的所有的弹窗
  • 截取网页的首页屏幕图片,获取网页的title属性,并且以titile命名截图文件
  • 获取页面中的所有图片,将图片地址保存到文件中
  • 最后关闭浏览器
二、实现讲解

从上一节 Puppeteer基础知识(一)我们学习的一些基础知识来看,需求中的要求步骤大部分都有对应的指令去做,很多步骤我们也是清楚的,我们将上一步骤学习的指令合并起来就可以实现这个需求了,对于缺少的部分,我们也会在本次进行添加。

废话不多说,我们开始实现脚本命令吧。

  • 定义page并打开网站

这里,定义网页属性调用的page对象,打开整个浏览器窗口,准备开始下面的操作。我们打开网址 https://blog.csdn.net/suwu150 进行实践。

  // headless 控制显示还是不显示
  const browser = await puppeteer.launch({
    headless: false,
    devtools: false, // 打开开发者模式
    defaultViewport: null, // 不使用默认的固定大小,直接填满浏览器
    slowMo: 50, // slow down by 250ms
  });
...

  await page.goto("https://blog.csdn.net/suwu150", { waitUntil: "networkidle2" });

  • 监听网站发出的所有请求,将请求存储到文件中
  • 屏蔽所有的弹窗

下面就是监听网络请求、监听日志打印和监听对话框的方式
在Puppeteer中对于事件的监听,需要采用语法 page.on 的形式去实现,我们可以在回调中响应对应的事件,这里分别监听了事件 console、request、dialog 三个事件,分别表示日志打印,请求发送和对话框弹窗事件,当然还有其他的事件,有兴趣的可以去官网看看,这里就不再说明了。戳我看看event api的详细说明:https://puppeteer.bootcss.com/api

  page.on('console', msg => console.log('PAGE LOG:', msg.text()));
  page.on('request', logRequest);
  page.on('dialog', async dialog => {
    console.log('dialog', await dialog.message());
    await dialog.dismiss();
    await dialog.dismiss();
    await dialog.dismiss();
  });

  let list = [];
  function logRequest(interceptedRequest) {
    console.log('A request was made:', interceptedRequest.url());
    list.push(interceptedRequest.url())
  }

当然,不仅仅能够监听网络请求去做记录保留,也能够在捕获到请求的时候,决定是否去发送真实的请求到后台获取数据,这就是去分析是否继续爬取下级页面的关键。如果我们判断后发现没必要再去深入了,就可以停止请求了。

举个例子🌰,来看看如何阻止:

  page.on('request', request => {
    if (request.resourceType() === 'image') {
      request.abort();
    } else {
      request.continue();
    }
  });

对于文件保存,我们定义了单独的方法 writeFile,方法内容如下:

  async function writeFile(path, content) {
    await new Promise((resolve, reject) => {
      fs.writeFile(path, content, () => {
        resolve();
      })
    });
  };

也是一个异步方法,通过 Promise 控制 fs 对文件 io 的操作,将需要保存的内容保存到本地,需要做的是传入当前保存的路径 path 以及需要保存的内容 content 即可。

  • 截取网页的首页屏幕图片,以titile命名
    通过page.title()获取title内容,然后定义作为名称保存。
  const title = await page.title()
  console.log('title', title)
  await page.screenshot({ path: `../images/${title}.png`, fullPage: true });

  • 获取页面中的所有图片,将图片地址保存到文件中
    下面是获取所有的图片,通过选择器page.$$eval拿到所有的img标签,获取到src属性,然后将图片 src 保存到指定的 csdn_images.json 文件中。这里所使用的保存文件的方式就是上面定义的 writeFile 方法。
  const imgArray =
   await page.$$eval('img', els => Array.from(els).map(el => el.getAttribute('src')));
  await writeFile('../json/csdn_images.json', JSON.stringify({ imgArray }, null, 2))
  • 关闭浏览器
  await browser.close();

以下是完整的实现,在项目中新增js文件,命名为 csdnImg.js ,增加以下内容:

const puppeteer = require('puppeteer');
const fs = require('fs');

(async () => {
  // headless 控制显示还是不显示
  const browser = await puppeteer.launch({
    headless: false,
    devtools: false, // 打开开发者模式
    defaultViewport: null, // 不使用默认的固定大小,直接填满浏览器
    slowMo: 50, // slow down by 250ms
  });
  let page = await browser.newPage();

  // 监听网站的console,发出的所有请求,dialog
  page.on('console', msg => console.log('PAGE LOG:', msg.text()));
  page.on('request', logRequest);
  page.on('dialog', async dialog => {
    console.log('dialog', await dialog.message());
    await dialog.dismiss();
    await dialog.dismiss();
    await dialog.dismiss();
  });

  let list = [];
  function logRequest(interceptedRequest) {
    console.log('A request was made:', interceptedRequest.url());
    list.push(interceptedRequest.url())
  }
  // 以模拟器的形式打开
  await page.emulate({
    viewport: {
      width: 375,
      height: 667,
      isMobile: true
    },
    userAgent: '"Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"'
  });

  //打开页面
  await page.goto("https://blog.csdn.net/suwu150", { waitUntil: "networkidle2" });

  await page.waitForTimeout(2600);
  await page.reload()

  // 截取屏幕,以titile形式保存
  const title = await page.title()
  console.log('title', title)
  await page.screenshot({ path: `../images/${title}.png`, fullPage: true });

  // 保存request请求
  await writeFile('../json/csdn.json', JSON.stringify({ list }, null, 2))

  // 保存图片src地址
  const imgArray = await page.$$eval('img', els => Array.from(els).map(el => el.getAttribute('src')));
  await writeFile('../json/csdn_images.json', JSON.stringify({ imgArray }, null, 2))

  // 关闭浏览器
  await browser.close();
  // 保存文件公共方法
  async function writeFile(path, content) {
    await new Promise((resolve, reject) => {
      fs.writeFile(path, content, () => {
        resolve();
      })
    });
  };
})();
三、效果查看

接下来,我们只需要在终端运行命令,执行文件

 node csdnImg.js 

就能够看到会自动打开浏览器进行按照我们页面代码中指定的命令操作。
同时,在项目文件系统中能够看到新增了以下内容

  • 在images下看到首页的截图:
    在这里插入图片描述

  • 在路径../json/csdn.json下保存请求历史路径
    在这里插入图片描述

  • ../json/csdn_images.json下,看到网页中图片的地址

在这里插入图片描述

以上就是整个的爬取过程。有兴趣的小伙吧感觉尝试下吧!!!


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

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

相关文章

【数据结构】线性表与顺序表

⭐ 作者:小胡_不糊涂 🌱 作者主页:小胡_不糊涂的个人主页 📀 收录专栏:浅谈Java 💖 持续更文,关注博主少走弯路,谢谢大家支持 💖 线性表与顺序表 1. 线性表2. 顺序表2.1 …

【Java 进阶篇】JavaScript 正则表达式(RegExp)详解

JavaScript 正则表达式,通常简写为 RegExp,是一种强大的文本匹配工具,它允许你通过一种灵活的语法来查找和替换字符串中的文本。正则表达式在编程中用途广泛,不仅限于 JavaScript,在许多编程语言中也都有类似的实现。 …

Spring MVC 十一:@EnableWebMvc

我们从两个角度研究EnableWebMvc: EnableWebMvc的使用EnableWebMvc的底层原理 EnableWebMvc的使用 EnableWebMvc需要和java配置类结合起来才能生效,其实Spring有好多Enablexxxx的注解,其生效方式都一样,通过和Configuration结合…

Hermes - 指尖上的智慧:自定义问答系统的崭新世界

在希腊神话中,有一位智慧与消息的传递者神祇,他就是赫尔墨斯(Hermes)。赫尔墨斯是奥林匹斯众神中的一员,传说他是乌尔阿努斯(Uranus)和莫伊拉(Maia)的儿子,同…

【Java 进阶篇】JavaScript Math对象详解

在JavaScript编程中,Math对象是一个非常有用的工具,用于执行各种数学运算。它提供了许多数学函数和常数,可以用于处理数字、执行几何运算、生成随机数等。在本篇博客中,我们将深入探讨JavaScript中Math对象的各种功能和用法。 什…

城市广告牌安全传感器特点有哪些?

城市广告牌安全传感器特点有哪些? 在现代快节奏的都市生活中,城市的广告牌成为不可或缺的一部分,以各种形式和大小存在于城市的街头巷尾,商业中心和交通要道。广告牌是城市生命线组成的一部分。但是由于天气因素、材料老化、不当维…

C++智能指针(三)——unique_ptr初探

与共享指针shared_ptr用于共享对象的目的不同,unique_ptr是用于独享对象。 文章目录 1. unqiue_ptr的目的2. 使用 unique_ptr2.1 初始化 unique_ptr2.2 访问数据2.3 作为类的成员2.4 处理数组 3. 转移所有权3.1 简单语法3.2 函数间转移所有权3.2.1 转移至函数体内3.…

VS Code:CMake配置

概述 在VSCode和编译器MinGW安装完毕后,要更高效率的进行C/C开发,采用CMake。CMake是一个开源、跨平台的编译、测试和打包工具,它使用比较简单的语言描述编译,安装的过程,输出Makefile或者project文件,再去…

【JavaEE】 饿汉模式与懒汉模式详解与实现

文章目录 🌴单例模式🍀饿汉模式🎍懒汉模式🚩单线程版(线程不安全)🚩多线程版🚩多线程版(改进) ⭕总结 🌴单例模式 单例模式是校招中最常考的设计模式之一. 那么啥是设计模式呢? 设…

五子棋(C语言实现)

目录 构思 1、主程序 2、初始化 3、游戏菜单 4、打印棋盘 6、玩家下棋 7、判断输赢 8、功能整合 人机下棋 完整版: game.h game.c text.c 测试功能代码 构思 五子棋不必多介绍了,大家小时候都玩过哈。 我们要通过程序实现这个小游戏&…

AI对网络安全的影响与挑战

近年来,随着人工智能(AI)技术的快速发展,网络安全领域也开始逐渐引入生成式AI应用。根据最新的数据研究,生成式AI对网络安全和合规的影响最大,同时也包括了IT和云的运维、硬件和软件支持领域。通过AI和自动…

Typora--博客必备神器

文章目录 一、下载typora二、创建文件前的操作1.显示扩展名2.typora设置和markdown语法2.1markdown语法2.2图片的管理2.3**高亮**2.4设置自动保存和调试 一、下载typora 进入typota.io网站,点击下载即可。 二、创建文件前的操作 1.显示扩展名 设置显示文件扩展名…

python+django学生选课管理系统_wxjjv

1)前台:首页、课程信息、校园论坛、校园公告、个人中心、后台管理。 (2)管理员:首页、个人中心、学生管理、教师管理课、程信息管理、课程分类管理、选课信息管理、作业信息管理、提交作业管理、学生成绩管理、校园论…

android studio 移植工程

第一步: 第二步:创建 第三步: 第四步:复制文件至替代新工程中的文件 第五步:修改 第六步:编译OK

第 125 场周赛 三元组

可恶,被longlong的长度卡住了,要是longlong再大一点就好了(bushi),其实是算法有问题,里面涉及1e9*1e9*1e9,longlong肯定存不下,一会儿去改改,先记录一下。 题目:竞赛 - …

树莓派玩转openwrt软路由:12.OpenWrt安装MySQL

1、安装MySQL #下载MySQL镜像 docker pull arm64v8/mysql:latest#运行MySQL镜像 docker run --name mysql --restartalways --privilegedtrue \ -v /usr/local/mysql/data:/var/lib/mysql \ -v /usr/local/mysql/conf.d:/etc/mysql/conf.d \ -e MYSQL_ROOT_PASSWORD123456 -p …

C++——C++入门

C 前言一、认识C二、C入门C关键字(C98)命名空间命名空间定义命名空间使用 C输入&输出缺省参数缺省参数概念缺省参数分类 函数重载函数重载概念C支持函数重载的原理--名字修饰(name Mangling) 总结 前言 C的学习开始啦! 来吧~让我们拥抱更广阔的知识海洋&#x…

msvcp140.dll文件下载方法,找不到msvcp140.dll丢失的解决方法

在我日常的计算机维护和故障排除工作中,我遇到了许多由于丢失或损坏MSVCP140.dll文件而导致的程序无法正常运行的问题。这个DLL文件是Microsoft Visual C 2010 Redistributable Package的一部分,它是许多Windows应用程序(尤其是使用C编写的程…

C++11中类与对象推出的新功能 [补充讲解final/override关键字]

文章目录 1.移动构造2.移动赋值对于移动构造/移动赋值的想法 3.类成员定义时初始化4.强制生成默认函数的关键字default5.禁止生成默认函数的关键字delete5.1介绍5.2应用场景1.法一:析构函数私有化2.法二: delete关键字思考 6.final关键字7.override关键字 1.移动构造 编译器自动…

Lambda表达式(JAVA)

注:如果没有学过匿名内部类和接口不推荐往下看。 Lambda表达式的语法: (parameters) -> expression 或 (parameters) ->{ statements; } parameters:表示参数列表;->:可理解为“被用于”的意思&#xff1b…