Browserless 网页抓取:Playwright 中的 NodeJS

什么是 Playwright?

Playwright 是一个用于 Web 测试和自动化的开源框架。基于 Node.js,由 Microsoft 开发,它通过单一 API 支持 Chromium、Firefox 和 WebKit。它可以在 Windows、Linux 和 macOS 上运行,并且兼容 TypeScript、JavaScript、Python、.NET 和 Java。

在 Playwright 中使用 NodeJS 进行 Web 爬取的优势是什么?

Playwright 不仅仅是一个工具,而是一个全面的 Web 爬取解决方案,结合了在 Node.js 中的强大功能、灵活性和效率,以满足现代 Web 自动化最苛刻的要求。

  • 强大的页面交互处理
  • 自动处理动态内容
  • 抗反爬技术的韧性

在 Node.js 中,Playwright 的无头模式是一个巨大的优势。它允许你在没有可视界面的情况下运行浏览器,加快了爬取过程,非常适合大规模任务。

Playwright 能够很好地处理复杂的 Web 交互,例如加载动态内容、管理用户输入和处理异步操作。这使得它非常适合从依赖 JavaScript 的现代网站中爬取数据。网络请求拦截功能是另一个强项。它让你可以控制请求和响应,帮助绕过反爬措施并优化你的爬取过程。

Playwright 的另一个优点是它与 Node.js 项目的集成非常简单。你可以轻松地将其融入现有的工作流程中,并与其他 JavaScript 或 TypeScript 库一起使用。此外,由于它可以跨 Windows、Linux 和 macOS 运行,你可以在不同的平台上部署爬取脚本而无需任何麻烦。

什么是 Browserless?

Browserless 是由 Nstbrowser 设计的基于云的无头浏览器服务,用于执行没有图形界面的 Web 操作和自动化脚本。

Browserless 的一个关键特性是它能够通过集成的 Anti-detect、Web Unblocker 和智能代理系统绕过常见的障碍,如 CAPTCHAs 和 IP 封锁。这些工具确保你的自动化脚本即使在具有严格安全措施的网站上也能顺利运行。

Browserless 支持云容器集群,使你能够轻松扩展操作。无论你是在 Windows、Linux 还是 macOS 上运行,我们的平台都能为你的 Web 自动化需求提供一致的企业级解决方案。它设计得非常适合与你现有的工作流程无缝集成,提供一个强大且可靠的高性能 Web 操作环境。

对 Web 爬取和 Browserless 有任何精彩的想法和疑问吗?
让我们看看其他开发者在 Discord 和 Telegram 上分享了什么!

如何使用 Playwright 和 NodeJS 进行 Web 爬取?

步骤1:安装和设置 PlaywrightPlaywright

首先,请确保你的系统上已安装 Node.js。如果没有,下载并安装 LTS 版本。之后,使用 Node.js 的包管理器 npm 安装 Playwright。

npm init playwright@latest

执行安装命令并进行以下选择以开始:

  • 在 TypeScript 和 JavaScript 之间选择(默认是 TypeScript)。
  • 命名你的测试文件夹(如果已经存在测试文件夹,则默认为 test 或 e2e)。
  • 选择是否添加 GitHub Actions 工作流,以便在 CI 上运行测试。
  • 确定是否立即安装 Playwright 浏览器(默认情况下为真,但你也可以稍后手动使用 npx playwright install 安装)。

步骤2:使用 Playwright 启动浏览器

像普通的浏览器一样,Playwright 也可以渲染 JavaScript、图像等,因此它可以提取动态加载的数据。由于它模拟正常的用户行为,脚本更难以检测和阻止。

import { chromium } from 'playwright';
const browser = await chromium.launch({ headless: false }); // 打开浏览器并创建一个新标签
const page = await browser.newPage();
await page.goto('https://developer.chrome.com/'); // 访问指定的 URL
await page.setViewportSize({ width: 1080, height: 1024 }); // 设置视口大小
console.log('[浏览器已打开!]');

默认情况下,Playwright 在无头模式下运行。在提供的代码中,我们通过设置 headless: false 来禁用无头模式,允许你可视化测试脚本。由于在 package.json 中启用了 "type": "module" 设置,允许 ES 模块执行,因此示例和以下代码不需要异步函数。

步骤3:开始爬取

我们将从一个基本的 Web 爬取任务开始,让你快速熟悉 Playwright。让我们提取 Amazon 上 Apple AirPods Pro 的评论!

有效的 Web 爬取始于 分析页面。你需要确定你想要提取的数据的位置。浏览器的调试控制台对我们非常有帮助:

打开网页后,你需要通过按 Ctrl + Shift + I(Windows/Linux)或 Cmd + Option + I(Mac)打开调试控制台。

  1. 在控制台的左上角选择元素选择器。
  2. 将鼠标悬停在你想要爬取的元素上,控制台中会高亮显示对应的 HTML 代码。

Playwright 支持各种选择元素的方法,但使用简单的 CSS 选择器通常是入门的最简单方式。之前使用的 .devsite-search-field 就是 CSS 选择器的一个例子。

对于复杂的 CSS 结构,调试控制台可以直接复制 CSS 选择器。右键点击你想抓取的元素 HTML,并选择 打开菜单 > 复制 > 复制选择器

现在选择器已经确定,我们可以使用 Playwright 尝试获取我上面选择的用户名。

import { chromium } from 'playwright';  // 你也可以使用 'firefox' 或 'webkit'
// 启动一个新的浏览器实例
const browser = await chromium.launch();
// 创建一个新页面
const page = await browser.newPage();
// 访问指定的 URL
await page.goto('https://www.amazon.com/Apple-Generation-Cancelling-Transparency-Personalized/product-reviews/B0CHWRXH8B/ref=cm_cr_dp_d_show_all_btm?ie=UTF8&reviewerType=all_reviews');
// 等待节点加载,最多等待10秒
await page.waitForSelector('div[data-hook="genome-widget"] .a-profile-name', { timeout: 10000 });
// 提取用户名
const username = await page.$eval('div[data-hook="genome-widget"] .a-profile-name', node => node.textContent);
console.log('[用户名]===>', username);
// 关闭浏览器
await browser.close();

你可以调整代码,不仅提取单个用户名,还可以提取完整的评论列表:

  • 使用 page.waitForSelector 确保评论元素完全加载。
  • 使用 page.$$ 选择所有匹配指定选择器的元素。

然后,循环遍历评论元素列表,并从每个元素中提取必要的信息。提供的代码将捕获标题、评分、用户名、文本内容和头像的 data-src 属性(包括头像的 URL)。

正如所展示的那样,代码:

  • page.goto 用于导航到所需页面。
  • waitForSelector 用于等待目标节点正确显示。
  • page.$eval 用于获取第一个匹配的元素,并通过回调函数提取特定属性。
await page.waitForSelector('div[data-hook="review"]');
const reviewList = await page.$$('div[data-hook="review"]');

接下来,我们需要遍历评论元素的列表并从每个评论元素中获取所需信息。

在以下代码中,我们可以获取内容的标题、评分、用户名和文本内容,以及头像元素节点的 data-src 属性值,这就是头像的 URL 地址。

for (const review of reviewList) {
  const title = await review.$eval(
    'a[data-hook="review-title"] > span:nth-of-type(2)',
    node => node.textContent,
  );
  const rate = await review.$eval(
    'i[data-hook="review-star-rating"] .a-icon-alt',
    node => node.textContent,
  );
  const username = await review.$eval(
    'div[data-hook="genome-widget"] .a-profile-name',
    node => node.textContent,
  );
  const avatar = await review.$eval(
    'div[data-hook="genome-widget"] .a-profile-avatar img',
    node => node.getAttribute('data-src'),
  );
  const content = await review.$eval(
    'span[data-hook="review-body"] span',
    node => node.textContent,
  );
  console.log('[log]===>', { title, rate, username, avatar, content });
}

第四步:导出数据

运行上述代码后,您应该能够在终端中看到日志信息的输出。

如果您想进一步保存这些数据,可以使用基本的 Node.js 模块 fs 将数据写入 JSON 文件,以便后续数据分析。以下是一个简单的工具函数:

import fs from 'fs';

// 保存为 JSON 文件
function saveObjectToJson(obj, filename) {
  const jsonString = JSON.stringify(obj, null, 2);
  fs.writeFile(filename, jsonString, 'utf8', (err) => {
    err ? console.error(err) : console.log(`文件保存成功:${filename}`);
  });
}

完整代码如下。运行后,您可以在当前脚本执行路径中找到 amazon_reviews_log.json 文件,记录了所有爬取的结果!

import { chromium } from 'playwright';
import fs from 'fs';
// 启动浏览器
const browser = await chromium.launch();
const page = await browser.newPage();
// 访问页面
await page.goto(
  `https://www.amazon.com/Apple-Generation-Cancelling-Transparency-Personalized/product-reviews/B0CHWRXH8B/ref=cm_cr_dp_d_show_all_btm?ie=UTF8&reviewerType=all_reviews`
);

// 等待评论元素加载
await page.waitForSelector('div[data-hook="review"]');
// 获取所有评论元素
const reviewList = await page.$$('div[data-hook="review"]');
const reviewLog = [];

// 遍历评论元素列表
for (const review of reviewList) {
  const title = await review.$eval(
    'a[data-hook="review-title"] > span:nth-of-type(2)',
    node => node.textContent.trim()
  );
  const rate = await review.$eval(
    'i[data-hook="review-star-rating"] .a-icon-alt',
    node => node.textContent.trim()
  );
  const username = await review.$eval(
    'div[data-hook="genome-widget"] .a-profile-name',
    node => node.textContent.trim()
  );
  const avatar = await review.$eval(
    'div[data-hook="genome-widget"] .a-profile-avatar img',
    node => node.getAttribute('data-src')
  );
  const content = await review.$eval(
    'span[data-hook="review-body"] span',
    node => node.textContent.trim()
  );
  console.log('[log]===>', { title, rate, username, avatar, content });
  reviewLog.push({ title, rate, username, avatar, content });
}

// 保存为 JSON 文件
function saveObjectToJson(obj, filename) {
  const jsonString = JSON.stringify(obj, null, 2);
  fs.writeFile(filename, jsonString, 'utf8', (err) => {
    err ? console.error(err) : console.log(`文件保存成功:${filename}`);
  });
}

saveObjectToJson(reviewLog, 'amazon_reviews_log.json');
await browser.close();

使用 Playwright 进行其他网页操作

点击按钮

使用 page.click 点击按钮,并设置延迟以使操作更像人类操作。以下是一个简单的示例。

import { chromium } from 'playwright'
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://example.com/'); // 访问指定的 URL
await page.waitForTimeout(3000)
await page.click('p > a', { delay: 200 })

滚动页面

在 page.evaluate 上,可以通过调用 Window API 设置滚动条的位置。page.evaluate 是一个非常有用的 API:

import { chromium } from 'playwright'
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://www.nstbrowser.io/'); // 访问指定的 URL

// 滚动到页面底部
await page.evaluate(() => {
  window.scrollTo(0, document.documentElement.scrollHeight);
});

获取元素列表

要获取多个元素,我们可以使用 page.$$eval,它可以获取所有匹配指定选择器的元素,最后在回调函数中遍历这些元素以获取特定属性。

import { chromium } from 'playwright'
// 启动浏览器
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://news.ycombinator.com/');

await page.waitForSelector('.titleline > a')
// 获取文章标题
const titles = await page.$$eval('.titleline > a', elements =>
  elements.map(el => el.innerText)
);
// 输出捕获的标题
console.log('文章标题:');
titles.forEach((title, index) => console.log(`${index + 1}: ${title}`));

拦截 HTTP 请求

page.route 方法用于拦截页面上的请求。'**/*' 是一个通配符,表示匹配所有请求。然后可以在回调函数中处理所有请求。参数 route 用于设置请求是正常执行还是被中断,也可以用于重写响应。

import { chromium } from 'playwright'
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();

await page.route('**/*', (route) => {
  const request = route.request();
  // 拦截并阻止字体请求
  if (request.url().includes('https://fonts.gstatic.com/')) {
    route.fulfill({
      status: 404,
      contentType: 'image/x-icon',
      body: ''
    });
    console.log('图标请求已阻止');
  // 拦截并阻止样式表请求
  } else if (request.resourceType() === 'stylesheet') {
    route.abort();
    console.log('样式表请求已阻止');
  // 拦截并阻止图像请求
  } else if (request.resourceType() === 'image') {
    route.abort();
    console.log('图像请求已阻止');
  // 允许其他请求继续
  } else {
    route.continue();
  }
});

await page.goto('https://www.youtube.com/');

截图

Playwright 提供了开箱即用的截图 API,这是一个非常实用的功能。您可以通过 quality 控制截图文件的质量,并通过 clip 裁剪图像。如果您对截图比例有要求,可以设置 viewport 来实现。

import { chromium } from 'playwright';

const browser = await chromium.launch({ viewport: { width: 1920, height: 1080 } });
const page = await browser.newPage();
await page.goto('https://www.youtube.com/');

// 捕获整个页面
await page.screenshot({ path: 'screenshot1.png' });
// 捕获 JPEG 图像,将质量设置为 50
await page.screenshot({ path: 'screenshot2.jpeg', quality: 50 });
// 裁剪图像,指定裁剪区域
await page.screenshot({ path: 'screenshot3.jpeg', clip: { x: 0, y: 0, width: 150, height: 150 } });
console.log('截图已保存');
await browser.close();

Playwright vs. Puppeteer vs. Selenium

标准PlaywrightPuppeteerSelenium
浏览器支持Chromium, Firefox 和 WebKit基于 Chromium 的浏览器Chrome, Firefox, Safari, Internet Explorer 和 Edge
语言支持TypeScript, JavaScript, Python, .NET 和 JavaNode.jsJava, Python, C#, JavaScript, Ruby, Perl, PHP, TypeScript
操作系统Windows, macOS, LinuxWindows 和 OS XWindows, macOS, Linux, Solaris
社区和生态系统不断增长的社区,Microsoft 的强大支持和持续开发由 Google 支持的强大社区,特别适合关注 Chromium 的用户成立时间久,有庞大活跃的社区和广泛的生态系统,包括插件和集成
CI/CD 集成支持
录制和回放支持在 Chrome DevTools 的 Sources 面板中Playwright CodeGenSelenium IDE
网页抓取差异具有现代功能和速度,适合不同浏览器的抓取在 Chrome 中表现优秀,速度快多功能的网页抓取工具,但可能较慢
无头模式支持所有支持的浏览器的无头模式支持无头模式,但仅限于基于 Chromium 的浏览器支持无头模式,但实现因浏览器驱动而异
截图PDF 和图像捕获,尤其是在 Chromium 中PDF 和图像捕获,易于使用不支持内置 PDF 捕获

最终想法

Playwright 非常强大!

它提供了一个强大而多功能的网页抓取工具包。此外,Playwright 的出色文档和不断增长的社区为您的自动化任务带来了极大的便利。

在这篇博客中,您对 Playwright 有了更深入的了解:

  • Playwright 网页抓取的优势。
  • 在 Playwright 中高效使用 NodeJS。
  • 使用 Playwright 完成其他操作。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

设计模式六大原则(一)--单一职责原则

摘要 单一职责原则是设计模式六大原则之一,强调一个类应该仅有一个引起它变化的原因,即每个类应仅负责一项职责。本文通过详细探讨单一职责原则的定义、实现方式、优缺点及其适用场景,揭示了其在软件设计中的核心地位。通过类的拆分、接口设…

TCP协议段中的六个标志位

目录 ACK SYN RST FIN PSH URG TCP报文格式中的六个标志位由6个比特构成,在通信双方基于TCP协议互相发送报文数据时可以通过报头中标志位来区别对方发送的报文数据的请示。 ACK 确认号是否有效。 接收端对所收到的报文进行检查,若未发现错误&…

周易测算系统开发:融合古典智慧与现代技术的创新实践

一、引言 周易,作为中国古代文化的瑰宝,蕴含着深邃的哲学思想与预测智慧,其独特的六十四卦体系及爻变原理,自古以来便被人们用于探索自然规律、人生哲理及未来趋势。随着科技的飞速发展,将周易智慧与现代计算机技术相结…

StackStorm自动化平台

1. StackStorm概述 1.1 StackStorm介绍 StackStorm是一个开源的事件驱动自动化平台,它允许开发者和系统管理员自动化IT和网络操作。StackStorm结合了IT运维、DevOps和网络安全团队的需求,提供了一个集中式的工作流自动化解决方案,包括事件响…

图像数据处理13

三、空域滤波 3.1滤波器的基本概念 什么是滤波? 简单来说就是从干扰信号中提取出有用的信号 3.1.1空域滤波(Spatial Domain Filtering) 空域滤波适用于简单的滤波任务,直接对图像的像素空间进行操作。它通过对图像中的每个像…

ES 支持乐观锁吗?如何实现的?

本篇主要介绍一下Elasticsearch的并发控制和乐观锁的实现原理,列举常见的电商场景,关系型数据库的并发控制、ES的并发控制实践。 并发场景 不论是关系型数据库的应用,还是使用Elasticsearch做搜索加速的场景,只要有数据更新&…

ES6-ES13学习笔记

目录 初识ES6 变量声明 解构赋值 对象解构 ​编辑 数组解构 ​编辑模版字符串 字符串扩展 includes() repeat() startsWith() endsWith() 数值扩展 二进制和八进制表示法 (Number.)isFinite()与isNaN() Number.isInteger() Math.trunc …

AWS不同类型的EC2实例分别适合哪些场景?

Amazon Web Services(AWS)的弹性计算云(EC2)提供了多种实例类型,以满足不同的应用需求和工作负载。了解不同类型的 EC2 实例及其适用场景,可以帮助用户更好地优化性能和控制成本。九河云和大家一起了解一下…

元数据管理gravitino学习

元数据管理的组成有几个部分:Metaservice(Gravitino)、Luoshu(amoro)、Hive Metastore,其中gravitino是数据管理模块实现元数据统一管理的核心。前面有提到hive metastore可以存储hive的库表元数据信息,可以用于存储关于hive表、列…

一文读懂推荐系统

随着互联网的飞速发展,信息过载已经成为了一个普遍的问题。我们每天都要面对大量的内容,却很难找到真正符合自己兴趣和需求的信息。这时,推荐系统应运而生,它能够根据用户的兴趣和行为,智能地推荐相关内容,…

思特科技:国家宝藏数字体验馆展现东方美学 让“文物活起来”

01      思特科技为“国家宝藏数字体验展”提供“数字技术”支持,带来国宝的数字化演绎。以《国家宝藏》顶级IP为基础,打造的全新沉浸文化项目“国宝数字体验展“,借由文物的视角、站在历史的星河中,探寻时间长河中不变的智慧…

Mac文件需要分卷压缩怎么办 Mac上怎么解压分卷压缩的文件

在处理大型文件的传输和存储的时候,Mac用户常面临文件大小超过限制的问题。为了有效管理这些大文件,分卷压缩成为一种必不可少的解决方案。Mac文件需要分卷压缩怎么办?Mac上怎么解压分卷压缩的文件?本文将向你介绍如何使用BetterZ…

近视防控明星:蔡司小乐圆中期临床数据详解

近视防控明星:蔡司小乐圆中期临床数据详解 小乐圆镜片作为近视防控镜片里的明星产品,从22年5月上市以来防控效果就一直备受大家的关注。而最近中期临床试验的结果,给家长孩子吃了一颗定心丸。 本次实验中,240位受试者被随机分成三…

C语言函数详解(上)【库函数】

目录 前言 一、函数的概念 二、库函数 1.标准库和头文件 2.库函数使用方式 3.如何通过以上的网站查看库函数信息 (以sqrt为例) 3.1 功能 3.2 头文件包含 3.3 库函数文档的⼀般格式 1. 函数原型 ​编辑2. 函数功能介绍 ​编辑3. 参数和返…

基于vue3的模拟数据mock.js应用

一、mock.js介绍 Mock.js 是一个用于生成随机数据,拦截 Ajax 请求的 JavaScript 库。它主要用于前后端分离开发时,模拟后端数据接口,使得前端开发者在不需要后端实际编写接口的情况下,也能进行开发、测试。 1、主要功能 生成随…

别只知道Xmind了,这4款思维导图工具也都很实用!

作为一款十分知名的思维导图工具,Xmind确实是一款很好用的脑图工具。不仅操作流畅,功能丰富,还有很多素材可以使用。但是没有云同步功能,免费的功能也有限。如果大家想知道更多好用的思维导图工具的话,也可以看看这4个…

企业级web应用服务器tomcat

目录 一、Web技术 1.1 HTTP协议和B/S 结构 1.2 前端三大核心技术 1.2.1 HTML 1.2.2 CSS(Cascading Style Sheets)层叠样式表 1.2.3 JavaScript 二、tomcat的功能介绍 2.1 安装 tomcat 环境准备 2.1.1 安装java环境 2.1.2 安装并启动tomcat …

「数组」希尔排序 / 区间增量优化(C++)

目录 概述 思路 核心概念:增量d 算法过程 流程 Code 优化方案 区间增量优化 Code(pro) 复杂度 概述 我们在「数组」冒泡排序|选择排序|插入排序 / 及优化方案(C)中讲解了插入排序。 它有这么两个特点: ①待排序元素较…

路由偏好详解

路由偏好对网络性能和数据传输效率有着重要影响。本文将从路由偏好的相关概念、影响因素和实际应用,同时结合IP数据云的功能展示其在优化路由选择中的作用。 路由偏好指网络设备在选择路由路径时所倾向的特定策略或条件。它基于多种因素进行决策,例如网络…

CSS继承、盒子模型、float浮动、定位、diaplay

一、CSS继承 1.文字相关的样式会被子元素继承。 2.布局样式相关的不会被子元素继承。(用inherit可以强行继承) 实现效果: 二、盒子模型 每个标签都有一个盒子模型,有内容区、内边距、边框、外边距。 从内到外:cont…