Puppeteer让你网页操作更简单(2)抓取数据

news2024/11/18 23:39:48

Puppeteer让你网页操作更简单(1)屏幕截图】

示例2 —— 让我们抓取一些数据

现在您已经了解了Headless Chrome和Puppeteer的工作原理基础知识,让我们看一个更复杂的示例,其中我们实际上可以抓取一些数据。

首先,请查看此处的Puppeteer API文档。如您所见,有大量不同的方法我们可以使用不仅可以在网站上点击,还可以填写表单、输入内容并读取数据。

在本教程中,我们将抓取Books To Scrape,这是一家专门用于帮助人们练习抓取的假书店。

在同一目录中创建一个名为scrape.js的文件,并插入以下样板代码:

const puppeteer = require('puppeteer');

let scrape = async () => {
  // Actual Scraping goes Here...
  
  // Return a value
};

scrape().then((value) => {
    console.log(value); // Success!
});

理想情况下,经过第一个示例的学习,上述代码对您来说是有意义的。 如果不是,没关系!

我们上面所做的就是要求之前安装的 puppeteer 依赖项。然后我们有 scrape() 函数,我们将在其中输入抓取代码。该函数将返回一个值。最后,我们调用 scrape 函数并处理返回值(将其记录到控制台)。

我们可以通过在 scrape 函数中添加一行代码来测试上述代码。试试这个:

let scrape = async () => {
  return 'test'; 
};

现在在控制台中运行 node scrape.js。您应该会看到 test 被返回!完美,我们的返回值被记录到了控制台。现在我们可以开始填充 scrape 函数了。

步骤 1:设置

我们需要做的第一件事是创建浏览器的实例,打开一个新页面,并导航到一个 URL。我们是这样做的:

let scrape = async () => {
  const browser = await puppeteer.launch({headless: false});
  const page = await browser.newPage();
  await page.goto('http://books.toscrape.com/');
  await page.waitFor(1000);  
  // 抓取
  browser.close();
  return result;
};

很棒!让我们一行一行地分解它:

首先,我们创建浏览器并将 headless 模式设置为 false。这使我们可以完全看到正在发生的事情:

const browser = await puppeteer.launch({headless: false}); 

然后,我们在浏览器中创建一个新页面:

const page = await browser.newPage();

接下来,我们转到 books.toscrape.com URL:

await page.goto('http://books.toscrape.com/');

另外,我添加了 1000 毫秒的延迟。虽然通常不必要,但这可以确保页面上的所有内容都加载:

await page.waitFor(1000);

最后,完成所有工作后,我们将关闭浏览器并返回结果。

browser.close();
return result; 

设置完成。现在,让我们开始抓取!

步骤 2:抓取

如您到目前所了解的,Books to Scrape 有大量真实书籍和这些书籍的虚拟数据。我们要做的是选择页面上的第一本书,并返回该书的标题和价格。这是 Books to Scrape 的主页。我有兴趣单击第一本书(如下红色突出显示)

查看 Puppeteer API,我们可以找到允许我们在页面上点击的方法:

page.click(selector[, options])

  • selector 要搜索要单击的元素的选择器。如果有多个元素满足选择器,将单击第一个元素。

幸运的是,Google Chrome 开发者工具可以非常轻松地确定特定元素的选择器。只需右键单击图像并选择检查:

这将打开元素面板,元素被突出显示。您现在可以在左侧单击三个点,选择复制,然后选择复制选择器:

太棒了!我们现在已经复制了选择器,可以将点击方法插入程序中。就是这样:

await page.click('#default > div > div > div > div > section > div:nth-child(2) > ol > li:nth-child(1) > article > div.image_container > a > img');

我们的窗口现在将点击第一张产品图片并导航到该产品页面!

在新页面上,我们对产品标题和产品价格感兴趣 —— 如下红色部分所示

为了检索这些值,我们将使用 page.evaluate() 方法。该方法允许我们使用内置的 DOM 选择器,如 querySelector()。

我们要做的第一件事是创建 page.evaluate() 函数并将返回的值保存到名为 result 的变量中:

const result = await page.evaluate(() => {
// 返回一些内容 
});

在我们的函数中,我们可以选择所需的元素。我们将再次使用 Google 开发者工具来解决这个问题。右键单击标题并选择检查:

如您在元素面板中所见,标题只是一个 h1 元素。我们现在可以使用以下代码选择该元素:

let title = document.querySelector('h1'); 

由于我们想要该元素中包含的文本,因此我们需要添加 .innerText —— 这是最终代码的样子:

let title = document.querySelector('h1').innerText;

类似地,我们可以通过右键单击并检查元素来选择价格:

在这里插入图片描述

如您所见,我们的价格具有 price_color 类。我们可以使用此类来选择元素及其内部文本。代码如下:

let price = document.querySelector('.price_color').innerText;

现在我们已经获取了所需的文本,可以在对象中返回它:

return {
  title, 
  price
}

很棒!我们现在正在选择标题和价格,将它们保存到对象中,并将该对象的值返回到 result 变量中。将所有部分组合在一起的样子如下:

const result = await page.evaluate(() => {
  let title = document.querySelector('h1').innerText;
  let price = document.querySelector('.price_color').innerText;
  return {
    title,
    price
  }
});

现在唯一要做的就是返回我们的 result,以便将其记录到控制台:

return result;

您的最终代码应如下所示:

onst puppeteer = require('puppeteer');

let scrape = async () => {
    const browser = await puppeteer.launch({headless: false});
    const page = await browser.newPage();

    await page.goto('http://books.toscrape.com/');
    await page.click('#default > div > div > div > div > section > div:nth-child(2) > ol > li:nth-child(1) > article > div.image_container > a > img');
    await page.waitFor(1000);

    const result = await page.evaluate(() => {
        let title = document.querySelector('h1').innerText;
        let price = document.querySelector('.price_color').innerText;

        return {
            title,
            price
        }

    });

    browser.close();
    return result;
};

scrape().then((value) => {
    console.log(value); // Success!
});

您现在可以通过在控制台中输入以下命令来运行 Node 文件:

node scrape.js
// { title: 'A Light in the Attic', price: '£51.77' }

您应该会在屏幕上看到所选书籍的标题和价格被返回!您刚刚抓取了网络!

示例3——完善它

现在您可能会问自己,为什么我们要点击书籍,而标题和价格都显示在主页上? 为什么不从那里抓取它们? 而且,为什么不抓取所有书籍的标题和价格呢?

因为抓取网站有很多种方法! (另外,如果我们留在主页上,我们的标题会被截断)。 然而,这为您提供了练习新抓取技能的绝佳机会!

挑战

目标 —— 从主页抓取所有书籍的标题和价格,并将它们返回到数组中。 这是我的最终输出样子:

去吧! 看看您是否可以自己完成这项工作。 它与我们刚刚创建的程序非常相似。 如果您遇到困难,请向下滚动…

提示:

与前面的示例相比,此挑战的主要区别在于需要循环大量结果。 您可以按照以下方式设置代码以执行此操作:

const result = await page.evaluate(() => {
  let data = []; // 创建一个空数组

  let elements = document.querySelectorAll('xxx'); // 选择所有元素

  // 循环每个产品
  // 选择标题
  // 选择价格
  
  data.push({title, price}); // 将数据推送到我们的数组

  return data; // 返回我们的数据数组
});

解决方案:

const puppeteer = require('puppeteer');

let scrape = async () => {
    const browser = await puppeteer.launch({headless: false});
    const page = await browser.newPage();

    await page.goto('http://books.toscrape.com/');

    const result = await page.evaluate(() => {
        let data = []; // Create an empty array that will store our data
        let elements = document.querySelectorAll('.product_pod'); // Select all Products

        for (var element of elements){ // Loop through each proudct
            let title = element.childNodes[5].innerText; // Select the title
            let price = element.childNodes[7].children[0].innerText; // Select the price

            data.push({title, price}); // Push an object with the data onto our array
        }

        return data; // Return our data array
    });

    browser.close();
    return result; // Return the data
};

scrape().then((value) => {
    console.log(value); // Success!
    });

在这里插入图片描述

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

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

相关文章

Python教程39:使用turtle画今天日期

---------------turtle源码集合--------------- Python教程36:海龟画图turtle写春联 Python源码35:海龟画图turtle画中国结 Python源码31:海龟画图turtle画七道彩虹 Python源码30:海龟画图turtle画紫色的小熊 Python源码29&a…

10.9.2 std::function 非OO的多态实现 Page185~187

源代码&#xff1a; #include <iostream> #include <functional> #include <list>using namespace std;//使用function模板类定义一个类型&#xff0c; //该类型要求作为T的 //函数类型是参数是string,返回值是void typedef std::function <void (std::s…

MySQL-多表联合查询

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…

【算法实验】实验1

实验1-1 斐波那契数 【问题描述】斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。 定义&#xff1a;F(0) 0, F(1) 1, F(n) F(n-1) F(n-2) 其中n>1 要求计…

1、计算机的硬件组成、校验码

计算机的硬件组成 CPU的组成与功能 CPU的组成 CPU主要是由运算器、控制器、寄存器组和内部总线等部件组成 CPU的功能 1、程序控制通过执行指令来控制程序的执行顺序2、操作功能一条指令的实现需要若干操作信号配合&#xff0c;控制相应的部件完成相对应的操作3、时间控制对…

idea2020.1 x64实现git的push

今天还有点时间&#xff0c;顺便写一下这个。 我这边只说一下远程仓库&#xff08;gitee&#xff09;的push 点击之后会弹出 点击&#xff0c;弹出 输入你定义的远程仓库名&#xff08;自己起&#xff09;&#xff0c;以及url&#xff0c;url由下面获取 在你的gitee创建好仓库…

Marin说PCB之传输线损耗---趋肤效应和导体损耗01

大家在做RF上的PCB走线或者是车载相机的上走线的时候经常会听那些硬件工程师们说你这个走线一定要保证50欧姆的阻抗匹配啊&#xff0c;还有就是记得加粗走做隔层参考。 有的公司的EE硬件同事会很贴心的把RF走线的注意事项给你备注在原理图上或者是layoutguide上&#xff0c;遇到…

Rust-函数

简介 Rust的函数使用关键字fn开头。 函数可以有一系列的输入参数&#xff0c;还有一个返回类型。 函数体包含一系列的语句(或者表达式)。 函数返回可以使用return语句&#xff0c;也可以使用表达式。 Rust编写的可执行程序的入口就是fn main()函数。 以下是一个函数的示例…

Puppeteer让你网页操作更简单(1)屏幕截图

网页自动化设计爬虫工具 中就使用了Puppeteer进行对网页自动化处理&#xff0c;今天就来看看它是什么东西&#xff01; 我们将学习什么? 在本教程中,您将学习如何使用JavaScript自动化和抓取 web。 为此,我们将使用Puppeteer。 Puppeteer是一个Node库API,允许我们控制无头Ch…

在Eureka中注册多个服务(根据本地主机端口号区分)

这篇文章主要介绍如何在Eureka注册中心内注册多个EurekaServer服务端 建项目 创建一个Maven项目&#xff0c;在里面创建三个小的Maven空项目&#xff0c;具体结构如下。 EurekaServer3&#xff0c;即外面的大模块&#xff0c;为了清楚的观察项目结构&#xff0c;我将其src文…

Python data Structures: Strings, Files, Lists

Python data Structures 这门课是在coursera上由美国密歇根大学开展的公开课。python零基础可以选择course1,这是course2&#xff0c;我用来复习和补充的。本章将复习字符串、文件、列表。 Python是这样的&#xff0c;没学一次都有新的发现&#xff0c;补充以前遗漏的地方。 …

助力工业园区作业违规行为检测预警,基于YOLOv7【tiny/l/x】不同系列参数模型开发构建工业园区场景下作业人员违规行为检测识别系统

在很多工业园区生产作业场景下保障合规合法进行作业生产操作&#xff0c;对于保护工人生命安全降低安全隐患有着非常重要的作用&#xff0c;但是往往在实际的作业生产中&#xff0c;因为一个安全观念的淡薄或者是粗心大意&#xff0c;对于纪律约束等意思薄弱&#xff0c;导致在…

开发er们必知的Git命令

Git和GitHub是每位软件工程师都必须了解的最基本的东西。这些工具是开发人员日常工作的组成部分,因为我们每天都要与它们进行交互。熟练掌握Git不仅能简化您的生活,还能显著提高生产力。在这篇博文中,我们将探索一组命令,这些命令将大大提高您的生产力。随着您对这些命令的掌握…

【数据结构】八大排序之计数排序算法

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 一.计数排序简介及思想 二.计数排序代码实现 三.计数排序复杂度分析 &#x1f4cc;时间复杂度 &#x1f4cc;空间复杂度 结语 一.计数排序简介及思想 计数排序(Cou…

每日一博 - 使用APIFOX调测 @RequestBody标注的对象

文章目录 概述发送 post 请求步骤1.新建接口&#xff0c;设置为 post 请求2. 填写 URL 和参数3.发送请求 实战 RequestBody 概述 APIFOX&#xff08;类似Postman&#xff09;提供了丰富的功能来支持用户发送包含各种信息的 POST 请求&#xff0c;如文本数据、JSON 或 XML 数据…

雷达截面积RCS原理浅析

Radar Cross Section 雷达截面积&#xff08;Radar Cross Section&#xff09;是雷达扫描到物体的等效可见面积。具体来讲&#xff0c;RCS是一个虚拟的平面&#xff0c;该平面可以拦截该区域覆盖范围内的全部雷达能量&#xff0c;并且以漫反射形式将能量反射给雷达。雷达接受到…

在Android原生项目中 创建 Flutter模块

前言 应用场景&#xff1a;在已有的Android原生项目中&#xff0c;引入Flutter模块&#xff0c;摸索了两天&#xff0c;终于给整出来了&#xff1b; 如果是新项目&#xff0c;最好直接创建Flutter项目&#xff0c;然后在Fluter的 android / ios目录中&#xff0c;写原生代码&…

MYSQL的事务隔离

本章概览 mysql是一个支持多引擎的系统&#xff0c;并不是所有引擎都支持事务&#xff0c;本篇以innodb为例解析mysql在事务支持的实现。提到事务一定会想到ACID(Atomicity、Consistency、Isolation、Durability&#xff0c;即原子性、一致性、隔离性、持久性)&#xff0c;今天…

非线性方程求根迭代法(C++)

文章目录 问题描述算法描述不动点迭代法一维情形多维情形 牛顿迭代法单根情形重根情形 割线法抛物线法逆二次插值法 算法实现准备工作一般迭代法割线法抛物线法逆二次插值法 实例分析例1例2 迭代法是一种求解非线性方程根的方法, 它通过构造一个迭代过程, 将一个非线性方程转化…

智能手表喇叭无气孔导致老化播放后没声音

智能音箱喇叭老化播放后没声音 智能手表要做防水&#xff0c;在外壳上打了防水胶&#xff0c;结果出现播放突然没声音的现象&#xff0e; 原因 一直播放&#xff0c;设备温度升高&#xff0c;因为做了防水密闭导致喇叭腔体气压异常&#xff0c;导致播放没声音&#xff0e; …