”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 用 puppeteer 抓取网络!

用 puppeteer 抓取网络!

发布于2024-11-06
浏览:496

Scrape the web with puppeteer!

木偶师完整指南 pt.1

Puppeteer:Web 自动化的强大工具

在当今快节奏的 Web 开发环境中,自动化是关键,这就是 Puppeteer 的用武之地。Puppeteer 由 Google 开发,是一个功能强大的 Node.js 库,允许开发人员使用 JavaScript 控制 Chrome 浏览器。无论您是在无头模式下浏览网络以提高效率,还是在完整的浏览器中获得视觉反馈,Puppeteer 都可以让您比以往更轻松地自动执行网页抓取、测试等任务。有了 Puppeteer,曾经需要手动完成的工作现在只需一个脚本即可完成。

为什么要进行网页抓取?

在最近的一个项目中,我与一位客户合作,他的外汇交易社区需要一个登陆页面。他想要类似于您在 MarketWatch 或雅虎财经上看到的股票行情的东西,但他想要的不是股票,而是在网站上显示 1 美元的实时货币兑换率。

虽然有可用的 API 可以提供数据(具有使用限制和月费),但我看到了使用 Puppeteer 创建自定义解决方案的机会。通过预先投入一些时间,我能够免费抓取和显示数据,最终为我的客户节省了经常性成本。

客户网站:Majesticpips.com

设置 puppeteer 变得简单

在我们开始抓取网络以实现其所有荣耀之前,我们必须将 puppeteer 安装到我们的应用程序中。

正如文档中所述

步骤1

使用您选择的 npm、yarn 或 pnpm 安装库。

  • npm 我木偶师

  • 纱线添加傀儡师

  • pnpm 添加木偶操纵者

这将在安装过程中下载 Chrome 的兼容版本,这对于初学者来说更容易快速启动和运行。

如果您是一位经验丰富的开发人员并且有您想要使用的特定 chrome/chromium 版本;然后安装这些软件包

  • npm i puppeteer-core

  • 纱线添加 puppeteer-core

  • pnpm 添加 puppeteer-core

最适合您,该软件包将是轻量级的,因为它只安装 puppeteer,而 chrome 版本则由您决定。

安装“puppeteer”对于初次测试者来说是更好的选择。它简化了设置并确保您拥有 Chromium 的工作版本,使您能够专注于编写脚本。

步骤2

现在在您的 JS 文件中,您需要为使用 ES 模块系统(ES6 标准)且节点版本为 12 及更高版本的应用程序导入 puppeteer。

从 'puppeteer' 导入 puppeteer; (受到推崇的)
或者
从 'puppeteer-core' 导入 puppeteer;

或者您可以使用 Node.js 的 commonJs 模块系统的 require 语法,该语法也与旧版本的 Node.js 兼容。

const puppeteer = require('puppeteer');
或者
const puppeteer = require('puppeteer-core');

步骤3

导入Puppeteer后,我们就可以开始编写执行网页抓取的命令了。下面的代码显示了您需要使用的内容。

我们使用库提供的这些方法启动浏览器。

const browser = await puppeteer.launch();

const page = await browser.newPage();

await browser.close();

puppeteer.launch() = 此方法启动一个新的浏览器实例。

browser.newPage() = 此方法在浏览器实例中创建一个新页面(或选项卡)。

browser.close() = 此方法关闭浏览器实例。

在 puppeteer.launch() 中,我们可以传递参数来根据我们的喜好自定义浏览器启动。我们将在第 2 部分中更详细地介绍这一点。但是,默认情况下,puppeteer.launch() 具有预设值,例如将无头模式设置为 true。

步骤4

浏览器已经启动,现在我们有了一个可以上网的页面。让我们导航到我们将抓取一些数据的网站。

在此示例中,我们将从 qoutes 网站抓取数据。

 await page.goto(https://quotes.toscrape.com/)

 await page.screenshot({ path: 'screenshot.png' })

我添加了await page.screenshot({path:'screenshot.png'})。这是一个很好的工具,可以确保一切按计划进行。执行此代码时,您的项目目录中将有一个图像文件,用于捕获您正在抓取的网站的当前状态。您还可以根据自己的喜好调整文件名。

如果一切正常,则继续执行步骤 5。

步骤5

现在我们的脚本已经成型,让我们深入研究从网页提取数据的关键部分。这是我们的脚本到目前为止的样子:

const puppeteer = require('puppeteer');

(async () => {

const browser = await puppeteer.launch();

const page = await browser.newPage();

await page.goto(https://quotes.toscrape.com/)

await page.screenshot({ path: 'screenshot.png' })

 const quotesScraper = await page.evaluate(() => {

const quotes = document.querySelectorAll(".quote"); 
    const quotesArray = [];

   for (const quote of quotes) { 
       const texts = quote.querySelector(".text").innerText; 
         const author = quote.querySelector(".author").innerText;  

        quotesArray.push({
           quote: texts,
           author
         });

     }
     return quotesArray;
});

console.log(quotesScraper);

await browser.close();

})();

要验证数据是否已成功抓取,我们可以在 CLI 中运行节点“server-file-name”,数据将使用 console.log(quotesScraper);.
显示在控制台中

[
  {
    quote: '“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”',
    author: 'Albert Einstein'
  },
  {
    quote: '“It is our choices, Harry, that show what we truly are, far more than our abilities.”',
    author: 'J.K. Rowling'
  },
  {
    quote: '“There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.”',
    author: 'Albert Einstein'
  },
  {
    quote: '“The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.”',
    author: 'Jane Austen'
  },
  {
    quote: "“Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.”",
    author: 'Marilyn Monroe'
  }
....
]

await page.evaluate(() => { ... }):这就是奇迹发生的地方。 evaluate 方法允许我们在正在抓取的页面上下文中运行 JavaScript 代码。这就好像您打开浏览器的开发者控制台并直接在页面上运行代码。

const quote = document.querySelectorAll(".quote");:在这里,我们选择页面上与 .quote 类匹配的所有元素。这给了我们一个引用元素的 NodeList。

constquotesArray = [];:我们初始化一个空数组来存储我们提取的引号。

for (const quote of quote) { ... }:此循环迭代每个引号元素。对于每一个,我们都会提取引用文本和作者。

quotesArray.push({ quote: texts,author });:对于每个引用,我们创建一个包含引用文本和作者的对象,然后将该对象推入quotesArray。

returnquotesArray;:最后,我们返回引号数组,然后将其存储在 Node.js 环境中的quotesScraper中。

这种提取数据的方法非常强大,因为它允许您像用户一样与页面交互,但是以自动化和编程的方式。

关闭浏览器

await browser.close();:抓取数据后,关闭浏览器以释放资源非常重要。此行确保我们启动的浏览器实例正确关闭。

展望第二部分

通过此脚本,您已成功使用 Puppeteer 从网站抓取数据。但我们只是触及了可能性的表面。在第 2 部分中,我们将探索更高级的技术,例如处理动态内容并使用 Express.JS 创建报废数据的 API 功能。 请继续关注,我们将深入探索 Puppeteer 的世界!

版本声明 本文转载于:https://dev.to/cedsengine/scrape-the-web-with-puppeteer-2hmh?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何使用Python理解有效地创建字典?
    如何使用Python理解有效地创建字典?
    在python中,词典综合提供了一种生成新词典的简洁方法。尽管它们与列表综合相似,但存在一些显着差异。与问题所暗示的不同,您无法为钥匙创建字典理解。您必须明确指定键和值。 For example:d = {n: n**2 for n in range(5)}This creates a dicti...
    编程 发布于2025-03-26
  • HTML格式标签
    HTML格式标签
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    编程 发布于2025-03-26
  • 为什么我会收到MySQL错误#1089:错误的前缀密钥?
    为什么我会收到MySQL错误#1089:错误的前缀密钥?
    mySQL错误#1089:错误的前缀键错误descript [#1089-不正确的前缀键在尝试在表中创建一个prefix键时会出现。前缀键旨在索引字符串列的特定前缀长度长度,可以更快地搜索这些前缀。了解prefix keys `这将在整个Movie_ID列上创建标准主键。主密钥对于唯一识别...
    编程 发布于2025-03-26
  • 为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    在CSS 问题:不正确的代码: 全球范围将所有余量重置为零,如提供的代码所建议的,可能会导致意外的副作用。解决特定的保证金问题是更建议的。 例如,在提供的示例中,将以下代码添加到CSS中,将解决余量问题: body H1 { 保证金顶:-40px; } 此方法更精确,避免了由全局保证金重置引...
    编程 发布于2025-03-26
  • 如何配置Pytesseract以使用数字输出的单位数字识别?
    如何配置Pytesseract以使用数字输出的单位数字识别?
    Pytesseract OCR具有单位数字识别和仅数字约束 在pytesseract的上下文中,在配置tesseract以识别单位数字和限制单个数字和限制输出对数字可能会提出质疑。 To address this issue, we delve into the specifics of Te...
    编程 发布于2025-03-26
  • 如何在Java字符串中有效替换多个子字符串?
    如何在Java字符串中有效替换多个子字符串?
    在java 中有效地替换多个substring,需要在需要替换一个字符串中的多个substring的情况下,很容易求助于重复应用字符串的刺激力量。 However, this can be inefficient for large strings or when working with nu...
    编程 发布于2025-03-26
  • 如何使用PHP从XML文件中有效地检索属性值?
    如何使用PHP从XML文件中有效地检索属性值?
    从php $xml = simplexml_load_file($file); foreach ($xml->Var[0]->attributes() as $attributeName => $attributeValue) { echo $attributeName,...
    编程 发布于2025-03-26
  • 如何使用Regex在PHP中有效地提取括号内的文本
    如何使用Regex在PHP中有效地提取括号内的文本
    php:在括号内提取文本在处理括号内的文本时,找到最有效的解决方案是必不可少的。一种方法是利用PHP的字符串操作函数,如下所示: 作为替代 $ text ='忽略除此之外的一切(text)'; preg_match('#((。 &&& [Regex使用模式来搜索特...
    编程 发布于2025-03-26
  • 如何在Java中执行命令提示命令,包括目录更改,包括目录更改?
    如何在Java中执行命令提示命令,包括目录更改,包括目录更改?
    在java 通过Java通过Java运行命令命令可能很具有挑战性。尽管您可能会找到打开命令提示符的代码段,但他们通常缺乏更改目录并执行其他命令的能力。 solution:使用Java使用Java,使用processBuilder。这种方法允许您:启动一个过程,然后将其标准错误重定向到其标准输出。...
    编程 发布于2025-03-26
  • 如何解决由于Android的内容安全策略而拒绝加载脚本... \”错误?
    如何解决由于Android的内容安全策略而拒绝加载脚本... \”错误?
    Unveiling the Mystery: Content Security Policy Directive ErrorsEncountering the enigmatic error "Refused to load the script..." when deployi...
    编程 发布于2025-03-26
  • 如何使用替换指令在GO MOD中解析模块路径差异?
    如何使用替换指令在GO MOD中解析模块路径差异?
    在使用GO MOD时,在GO MOD 中克服模块路径差异时,可能会遇到冲突,其中3个Party Package将另一个PAXPANCE带有导入式套件之间的另一个软件包,并在导入式套件之间导入另一个软件包。如回声消息所证明的那样: go.etcd.io/bbolt [&&&&&&&&&&&&&&&&...
    编程 发布于2025-03-26
  • 如何将PANDAS DataFrame列转换为DateTime格式并按日期过滤?
    如何将PANDAS DataFrame列转换为DateTime格式并按日期过滤?
    Transform Pandas DataFrame Column to DateTime FormatScenario:Data within a Pandas DataFrame often exists in various formats, including strings.使用时间数据时...
    编程 发布于2025-03-26
  • 如何从Google API中检索最新的jQuery库?
    如何从Google API中检索最新的jQuery库?
    从Google APIS 问题中提供的jQuery URL是版本1.2.6。对于检索最新版本,以前有一种使用特定版本编号的替代方法,它是使用以下语法:获取最新版本:未压缩)While these legacy URLs still remain in use, it is recommended ...
    编程 发布于2025-03-26
  • Python读取CSV文件UnicodeDecodeError终极解决方法
    Python读取CSV文件UnicodeDecodeError终极解决方法
    在试图使用已内置的CSV模块读取Python中时,CSV文件中的Unicode Decode Decode Decode Decode decode Error读取,您可能会遇到错误的错误:无法解码字节 在位置2-3中:截断\ uxxxxxxxx逃脱当CSV文件包含特殊字符或Unicode的路径逃...
    编程 发布于2025-03-26
  • 版本5.6.5之前,使用current_timestamp与时间戳列的current_timestamp与时间戳列有什么限制?
    版本5.6.5之前,使用current_timestamp与时间戳列的current_timestamp与时间戳列有什么限制?
    在时间戳列上使用current_timestamp或MySQL版本中的current_timestamp或在5.6.5 此限制源于遗留实现的关注,这些限制需要对当前的_timestamp功能进行特定的实现。 创建表`foo`( `Productid` int(10)unsigned not n...
    编程 发布于2025-03-26

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3